mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #70900 from mikeash/swift-generic-metadata-builder-out-of-process
[Tools] Add a library to build specialized generic metadata out of process.
This commit is contained in:
@@ -215,6 +215,10 @@ option(SWIFT_BUILD_REMOTE_MIRROR
|
||||
"Build the Swift Remote Mirror Library"
|
||||
TRUE)
|
||||
|
||||
option(SWIFT_BUILD_EXTERNAL_GENERIC_METADATA_BUILDER
|
||||
"Build the Swift External Generic Metadata Builder Library"
|
||||
TRUE)
|
||||
|
||||
option(SWIFT_BUILD_DYNAMIC_STDLIB
|
||||
"Build dynamic variants of the Swift standard library"
|
||||
TRUE)
|
||||
@@ -222,11 +226,11 @@ option(SWIFT_BUILD_DYNAMIC_STDLIB
|
||||
option(SWIFT_BUILD_STATIC_STDLIB
|
||||
"Build static variants of the Swift standard library"
|
||||
FALSE)
|
||||
|
||||
|
||||
option(SWIFT_STDLIB_STATIC_PRINT
|
||||
"Build compile-time evaluated vprintf()"
|
||||
FALSE)
|
||||
|
||||
|
||||
option(SWIFT_STDLIB_ENABLE_UNICODE_DATA
|
||||
"Include Unicode data files in the standard library.
|
||||
NOTE: Disabling this will cause many String methods to crash."
|
||||
@@ -1256,6 +1260,11 @@ if(SWIFT_BUILD_REMOTE_MIRROR)
|
||||
message(STATUS "")
|
||||
endif()
|
||||
|
||||
if(SWIFT_BUILD_EXTERNAL_GENERIC_METADATA_BUILDER)
|
||||
message(STATUS "Building Swift External Generic Metadata Builder for SDKs: ${SWIFT_SDKS}")
|
||||
message(STATUS "")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Find required dependencies.
|
||||
#
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
# * llvm-toolchain-dev-tools -- install LLVM development tools useful in a shared toolchain
|
||||
# * dev -- headers and libraries required to use Swift compiler as a library.
|
||||
set(_SWIFT_DEFINED_COMPONENTS
|
||||
"autolink-driver;back-deployment;compiler;clang-builtin-headers;clang-resource-dir-symlink;clang-builtin-headers-in-clang-resource-dir;libexec;stdlib;stdlib-experimental;sdk-overlay;static-mirror-lib;swift-syntax-lib;editor-integration;tools;testsuite-tools;toolchain-tools;toolchain-dev-tools;llvm-toolchain-dev-tools;dev;license;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers")
|
||||
"autolink-driver;back-deployment;compiler;clang-builtin-headers;clang-resource-dir-symlink;clang-builtin-headers-in-clang-resource-dir;libexec;stdlib;stdlib-experimental;sdk-overlay;static-mirror-lib;swift-syntax-lib;editor-integration;tools;testsuite-tools;toolchain-tools;toolchain-dev-tools;llvm-toolchain-dev-tools;dev;license;sourcekit-xpc-service;sourcekit-inproc;swift-remote-mirror;swift-remote-mirror-headers;swift-external-generic-metadata-builder;swift-external-generic-metadata-builder-headers")
|
||||
|
||||
# The default install components include all of the defined components, except
|
||||
# for the following exceptions.
|
||||
|
||||
@@ -151,7 +151,7 @@ template <typename Runtime>
|
||||
struct TargetTypeMetadataHeaderBase {
|
||||
/// A pointer to the value-witnesses for this type. This is only
|
||||
/// present for type metadata.
|
||||
TargetPointer<Runtime, const ValueWitnessTable> ValueWitnesses;
|
||||
TargetPointer<Runtime, const TargetValueWitnessTable<Runtime>> ValueWitnesses;
|
||||
};
|
||||
|
||||
template <typename Runtime>
|
||||
@@ -329,7 +329,7 @@ public:
|
||||
return asFullMetadata(this)->layoutString;
|
||||
}
|
||||
|
||||
const ValueWitnessTable *getValueWitnesses() const {
|
||||
const TargetValueWitnessTable<Runtime> *getValueWitnesses() const {
|
||||
return asFullMetadata(this)->ValueWitnesses;
|
||||
}
|
||||
|
||||
@@ -2979,7 +2979,7 @@ template <typename Runtime>
|
||||
struct swift_ptrauth_struct_context_descriptor(ModuleContextDescriptor)
|
||||
TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
|
||||
/// The module name.
|
||||
RelativeDirectPointer<const char, /*nullable*/ false> Name;
|
||||
TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> Name;
|
||||
|
||||
/// Is this module a special C-imported module?
|
||||
bool isCImportedContext() const {
|
||||
@@ -3036,7 +3036,7 @@ public:
|
||||
///
|
||||
/// Note that the Parent of the extension will be the module context the
|
||||
/// extension is declared inside.
|
||||
RelativeDirectPointer<const char> ExtendedContext;
|
||||
TargetRelativeDirectPointer<Runtime, const char> ExtendedContext;
|
||||
|
||||
using TrailingGenericContextObjects::getGenericContext;
|
||||
|
||||
@@ -3527,10 +3527,10 @@ struct TargetGenericValueMetadataPattern final :
|
||||
|
||||
/// The value-witness table. Indirectable so that we can re-use tables
|
||||
/// from other libraries if that seems wise.
|
||||
TargetRelativeIndirectablePointer<Runtime, const ValueWitnessTable>
|
||||
TargetRelativeIndirectablePointer<Runtime, const TargetValueWitnessTable<Runtime>>
|
||||
ValueWitnesses;
|
||||
|
||||
const ValueWitnessTable *getValueWitnessesPattern() const {
|
||||
const TargetValueWitnessTable<Runtime> *getValueWitnessesPattern() const {
|
||||
return ValueWitnesses.get();
|
||||
}
|
||||
|
||||
@@ -3825,9 +3825,11 @@ public:
|
||||
/*Nullable*/ true> AccessFunctionPtr;
|
||||
|
||||
/// A pointer to the field descriptor for the type, if any.
|
||||
TargetRelativeDirectPointer<Runtime, const reflection::FieldDescriptor,
|
||||
/*nullable*/ true> Fields;
|
||||
|
||||
TargetRelativeDirectPointer<Runtime,
|
||||
const reflection::TargetFieldDescriptor<Runtime>,
|
||||
/*nullable*/ true>
|
||||
Fields;
|
||||
|
||||
bool isReflectable() const { return (bool)Fields; }
|
||||
|
||||
MetadataAccessFunction getAccessFunction() const {
|
||||
|
||||
@@ -63,7 +63,8 @@ struct RuntimeTarget<8> {
|
||||
};
|
||||
|
||||
namespace reflection {
|
||||
class FieldDescriptor;
|
||||
template <typename Runtime>
|
||||
class TargetFieldDescriptor;
|
||||
}
|
||||
|
||||
/// In-process native runtime target.
|
||||
|
||||
@@ -590,8 +590,12 @@ public:
|
||||
using ValueTy = PointeeTy;
|
||||
using PointerTy = PointeeTy*;
|
||||
|
||||
Offset getOffset() const & {
|
||||
return RelativeOffsetPlusInt & ~getMask();
|
||||
}
|
||||
|
||||
PointerTy getPointer() const & {
|
||||
Offset offset = (RelativeOffsetPlusInt & ~getMask());
|
||||
Offset offset = getOffset();
|
||||
|
||||
// Check for null.
|
||||
if (Nullable && offset == 0)
|
||||
@@ -624,6 +628,7 @@ class RelativeDirectPointerIntPair<PointeeTy, IntTy, Nullable, Offset,
|
||||
{
|
||||
using super = RelativeDirectPointerIntPairImpl<PointeeTy, IntTy, Nullable, Offset>;
|
||||
public:
|
||||
using super::getOffset;
|
||||
using super::getPointer;
|
||||
using super::getInt;
|
||||
using super::getOpaqueValue;
|
||||
|
||||
@@ -264,6 +264,8 @@ public:
|
||||
// Only to be used by the demangler parsers.
|
||||
void removeChildAt(unsigned Pos);
|
||||
|
||||
void replaceChild(unsigned Pos, NodePointer Child);
|
||||
|
||||
// Reverses the order of children.
|
||||
void reverseChildren(size_t StartingAt = 0);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef SWIFT_REFLECTION_RECORDS_H
|
||||
#define SWIFT_REFLECTION_RECORDS_H
|
||||
|
||||
#include "swift/Basic/RelativePointer.h"
|
||||
#include "swift/ABI/TargetLayout.h"
|
||||
#include "swift/Demangling/Demangle.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
@@ -82,14 +82,15 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class FieldRecord {
|
||||
template <typename Runtime>
|
||||
class TargetFieldRecord {
|
||||
const FieldRecordFlags Flags;
|
||||
|
||||
public:
|
||||
const RelativeDirectPointer<const char> MangledTypeName;
|
||||
const RelativeDirectPointer<const char> FieldName;
|
||||
const TargetRelativeDirectPointer<Runtime, const char> MangledTypeName;
|
||||
const TargetRelativeDirectPointer<Runtime, const char> FieldName;
|
||||
|
||||
FieldRecord() = delete;
|
||||
TargetFieldRecord() = delete;
|
||||
|
||||
bool hasMangledTypeName() const {
|
||||
return MangledTypeName;
|
||||
@@ -111,36 +112,37 @@ public:
|
||||
return Flags.isVar();
|
||||
}
|
||||
};
|
||||
using FieldRecord = TargetFieldRecord<InProcess>;
|
||||
|
||||
struct FieldRecordIterator {
|
||||
const FieldRecord *Cur;
|
||||
const FieldRecord * const End;
|
||||
template <typename Runtime>
|
||||
struct TargetFieldRecordIterator {
|
||||
const TargetFieldRecord<Runtime> *Cur;
|
||||
const TargetFieldRecord<Runtime> *const End;
|
||||
|
||||
FieldRecordIterator(const FieldRecord *Cur, const FieldRecord * const End)
|
||||
: Cur(Cur), End(End) {}
|
||||
TargetFieldRecordIterator(const TargetFieldRecord<Runtime> *Cur,
|
||||
const TargetFieldRecord<Runtime> *const End)
|
||||
: Cur(Cur), End(End) {}
|
||||
|
||||
const FieldRecord &operator*() const {
|
||||
return *Cur;
|
||||
}
|
||||
const TargetFieldRecord<Runtime> &operator*() const { return *Cur; }
|
||||
|
||||
const FieldRecord *operator->() const {
|
||||
return Cur;
|
||||
}
|
||||
const TargetFieldRecord<Runtime> *operator->() const { return Cur; }
|
||||
|
||||
FieldRecordIterator &operator++() {
|
||||
TargetFieldRecordIterator &operator++() {
|
||||
++Cur;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const FieldRecordIterator &other) const {
|
||||
bool operator==(const TargetFieldRecordIterator &other) const {
|
||||
return Cur == other.Cur && End == other.End;
|
||||
}
|
||||
|
||||
bool operator!=(const FieldRecordIterator &other) const {
|
||||
bool operator!=(const TargetFieldRecordIterator &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
using FieldRecordIterator = TargetFieldRecordIterator<InProcess>;
|
||||
|
||||
enum class FieldDescriptorKind : uint16_t {
|
||||
// Swift nominal types.
|
||||
Struct,
|
||||
@@ -173,16 +175,17 @@ enum class FieldDescriptorKind : uint16_t {
|
||||
|
||||
// Field descriptors contain a collection of field records for a single
|
||||
// class, struct or enum declaration.
|
||||
class FieldDescriptor {
|
||||
const FieldRecord *getFieldRecordBuffer() const {
|
||||
return reinterpret_cast<const FieldRecord *>(this + 1);
|
||||
template <typename Runtime>
|
||||
class TargetFieldDescriptor {
|
||||
const TargetFieldRecord<Runtime> *getFieldRecordBuffer() const {
|
||||
return reinterpret_cast<const TargetFieldRecord<Runtime> *>(this + 1);
|
||||
}
|
||||
|
||||
public:
|
||||
const RelativeDirectPointer<const char> MangledTypeName;
|
||||
const RelativeDirectPointer<const char> Superclass;
|
||||
const TargetRelativeDirectPointer<Runtime, const char> MangledTypeName;
|
||||
const TargetRelativeDirectPointer<Runtime, const char> Superclass;
|
||||
|
||||
FieldDescriptor() = delete;
|
||||
TargetFieldDescriptor() = delete;
|
||||
|
||||
const FieldDescriptorKind Kind;
|
||||
const uint16_t FieldRecordSize;
|
||||
@@ -222,7 +225,7 @@ public:
|
||||
return const_iterator { End, End };
|
||||
}
|
||||
|
||||
llvm::ArrayRef<FieldRecord> getFields() const {
|
||||
llvm::ArrayRef<TargetFieldRecord<Runtime>> getFields() const {
|
||||
return {getFieldRecordBuffer(), NumFields};
|
||||
}
|
||||
|
||||
@@ -242,6 +245,7 @@ public:
|
||||
return Demangle::makeSymbolicMangledNameStringRef(Superclass.get());
|
||||
}
|
||||
};
|
||||
using FieldDescriptor = TargetFieldDescriptor<InProcess>;
|
||||
|
||||
// Associated type records describe the mapping from an associated
|
||||
// type to the type witness of a conformance.
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "swift/Runtime/Config.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
|
||||
struct OpaqueValue;
|
||||
struct InProcess;
|
||||
|
||||
@@ -139,7 +139,7 @@ void swift_initEnumMetadataMultiPayloadWithLayoutString(EnumMetadata *enumType,
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
unsigned swift_getEnumCaseMultiPayload(const OpaqueValue *value,
|
||||
const EnumMetadata *enumType);
|
||||
|
||||
|
||||
/// Store the tag value for the given case into a multi-payload enum,
|
||||
/// whose associated payload (if any) has already been initialized.
|
||||
SWIFT_RUNTIME_EXPORT
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Threading/Once.h"
|
||||
#include "swift/shims/Visibility.h"
|
||||
|
||||
namespace swift {
|
||||
namespace runtime {
|
||||
@@ -54,4 +55,4 @@ SWIFT_RUNTIME_STDLIB_SPI bool concurrencyValidateUncheckedContinuations();
|
||||
|
||||
} // end namespace environment
|
||||
} // end namespace runtime
|
||||
} // end namespace Swift
|
||||
} // end namespace swift
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#ifndef SWIFT_RUNTIME_GENERIC_METADATA_BUILDER_H
|
||||
#define SWIFT_RUNTIME_GENERIC_METADATA_BUILDER_H
|
||||
|
||||
#include "swift/ABI/Metadata.h"
|
||||
#include "swift/Basic/MathUtils.h"
|
||||
#include "swift/Demangling/TypeLookupError.h"
|
||||
@@ -26,8 +27,16 @@
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
// Use __FILE_NAME__ for logs when it's available, __FILE__ as a fallback.
|
||||
#ifdef __FILE_NAME__
|
||||
#define METADATA_BUILDER_LOG_FILE_NAME __FILE_NAME__
|
||||
#else
|
||||
#define METADATA_BUILDER_LOG_FILE_NAME __FILE__
|
||||
#endif
|
||||
|
||||
#define METADATA_BUILDER_LOG(...) \
|
||||
readerWriter.log(__FILE_NAME__, __LINE__, __func__, __VA_ARGS__)
|
||||
readerWriter.log(METADATA_BUILDER_LOG_FILE_NAME, __LINE__, __func__, \
|
||||
__VA_ARGS__)
|
||||
|
||||
namespace swift {
|
||||
|
||||
@@ -49,7 +58,7 @@ public:
|
||||
BuilderError(char *string) : errorString(string) {}
|
||||
|
||||
/// Make a BuilderError using a standard printf format string and arguments.
|
||||
[[gnu::format(printf, 2, 3)]] BuilderError(const char *fmt, ...) {
|
||||
SWIFT_FORMAT(2, 3) BuilderError(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
@@ -99,24 +108,24 @@ public:
|
||||
/// Get a pointer to the wrapped error, or NULL if the value is a success
|
||||
/// value.
|
||||
BuilderError *getError() { return std::get_if<BuilderError>(&storage); }
|
||||
};
|
||||
|
||||
/// This macro takes a value of BuilderErrorOr<T>. and produces an expression of
|
||||
/// type T. If this value is success, then the value of the expression is the
|
||||
/// wrapped success value. If it's an error, then this expression immediately
|
||||
/// returns the error from the enclosing function. This works by doing a return
|
||||
/// from the middle of a statement expression, which is scary, but works. We
|
||||
/// ultimately end up with something that looks a bit like a Swift `try`
|
||||
/// expression. Like Swift, we avoid using exceptions to propagate the error.
|
||||
#pragma clang diagnostic ignored \
|
||||
"-Wgnu-statement-expression-from-macro-expansion"
|
||||
#define ERROR_CHECK(errorOrT) \
|
||||
({ \
|
||||
auto error_check_tmp = (errorOrT); \
|
||||
if (auto *error = error_check_tmp.getError()) \
|
||||
return *error; \
|
||||
*error_check_tmp.getValue(); \
|
||||
})
|
||||
/// Allow manipulating the value with ->. `this` must not contain an error.
|
||||
T *operator->() {
|
||||
T *ptr = getValue();
|
||||
assert(ptr);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/// Get the value using *. `this` must not contain an error.
|
||||
T &operator*() {
|
||||
T *ptr = getValue();
|
||||
assert(ptr);
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
/// Objects are truthy if they contain a value, falsy for errors.
|
||||
operator bool() { return getValue() != nullptr; }
|
||||
};
|
||||
|
||||
/// A generic metadata builder. This is templatized on a ReaderWriter, which
|
||||
/// abstracts the various operations we need for building generic metadata, such
|
||||
@@ -194,9 +203,10 @@ class GenericMetadataBuilder {
|
||||
template <typename DescriptorType>
|
||||
BuilderErrorOr<const char *>
|
||||
getDescriptorName(Buffer<DescriptorType> descriptionBuffer) {
|
||||
auto name = ERROR_CHECK(
|
||||
descriptionBuffer.resolvePointer(&descriptionBuffer.ptr->Name));
|
||||
return name.ptr ? name.ptr : "<unknown>";
|
||||
auto name = descriptionBuffer.resolvePointer(&descriptionBuffer.ptr->Name);
|
||||
if (!name)
|
||||
return *name.getError();
|
||||
return name->ptr ? name->ptr : "<unknown>";
|
||||
}
|
||||
|
||||
/// Utility function for getting the location of an offset into a given
|
||||
@@ -278,13 +288,13 @@ public:
|
||||
"Writing %" PRIu16 " words of extra data from offset %" PRIu16,
|
||||
extraDataPattern->SizeInWords, extraDataPattern->OffsetInWords);
|
||||
auto patternPointers =
|
||||
ERROR_CHECK(patternBuffer.resolvePointer(&extraDataPattern->Pattern));
|
||||
patternBuffer.resolvePointer(&extraDataPattern->Pattern);
|
||||
for (unsigned i = 0; i < extraDataPattern->SizeInWords; i++) {
|
||||
auto patternPointer = ERROR_CHECK(
|
||||
patternPointers.resolvePointer(&patternPointers.ptr[i]));
|
||||
auto patternPointer =
|
||||
patternPointers->resolvePointer(&patternPointers->ptr[i]);
|
||||
data.writePointer(
|
||||
&metadataExtraData[i + extraDataPattern->OffsetInWords],
|
||||
patternPointer.template cast<const StoredPointer>());
|
||||
patternPointer->template cast<const StoredPointer>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,9 +302,9 @@ public:
|
||||
// The various initialization functions will instantiate this as
|
||||
// necessary.
|
||||
auto valueWitnesses =
|
||||
ERROR_CHECK(patternBuffer.resolvePointer(&pattern->ValueWitnesses));
|
||||
patternBuffer.resolvePointer(&pattern->ValueWitnesses);
|
||||
METADATA_BUILDER_LOG("Setting initial value witnesses");
|
||||
data.writePointer(&fullMetadata->ValueWitnesses, valueWitnesses);
|
||||
data.writePointer(&fullMetadata->ValueWitnesses, *valueWitnesses);
|
||||
|
||||
// Set the metadata kind.
|
||||
METADATA_BUILDER_LOG("Setting metadata kind %#x",
|
||||
@@ -313,9 +323,11 @@ public:
|
||||
installGenericArguments(WritableData<FullMetadata<Metadata>> data,
|
||||
Size metadataOffset,
|
||||
Buffer<const ValueTypeDescriptor> descriptionBuffer,
|
||||
const GenericArgument *arguments) {
|
||||
METADATA_BUILDER_LOG("Building %s",
|
||||
ERROR_CHECK(getDescriptorName(descriptionBuffer)));
|
||||
llvm::ArrayRef<GenericArgument> arguments) {
|
||||
auto name = getDescriptorName(descriptionBuffer);
|
||||
if (!name)
|
||||
return *name.getError();
|
||||
METADATA_BUILDER_LOG("Building %s", *name);
|
||||
char *metadataBase = reinterpret_cast<char *>(data.ptr);
|
||||
auto metadata =
|
||||
reinterpret_cast<ValueMetadata *>(metadataBase + metadataOffset);
|
||||
@@ -325,6 +337,11 @@ public:
|
||||
(reinterpret_cast<Pointer<const Metadata> *>(metadata) +
|
||||
getGenericArgumentOffset(
|
||||
descriptionBuffer.template cast<const TypeContextDescriptor>()));
|
||||
|
||||
if (arguments.size() < header.NumKeyArguments) {
|
||||
return BuilderError("Not enough generic arguments, %zu provided, %" PRId32 " required", arguments.size(), header.NumKeyArguments);
|
||||
}
|
||||
|
||||
METADATA_BUILDER_LOG(
|
||||
"Installing %" PRIu16 " generic arguments at offset %" PRId32,
|
||||
header.NumKeyArguments,
|
||||
@@ -353,7 +370,7 @@ public:
|
||||
/// Allocate and build a metadata structure.
|
||||
BuilderErrorOr<ConstructedMetadata>
|
||||
buildGenericMetadata(Buffer<const TypeContextDescriptor> descriptionBuffer,
|
||||
const GenericArgument *arguments,
|
||||
llvm::ArrayRef<GenericArgument> arguments,
|
||||
Buffer<const GenericMetadataPattern> patternBuffer,
|
||||
size_t extraDataSize) {
|
||||
auto description = descriptionBuffer.ptr;
|
||||
@@ -377,7 +394,7 @@ public:
|
||||
|
||||
BuilderErrorOr<ConstructedMetadata> buildGenericValueMetadata(
|
||||
Buffer<const ValueTypeDescriptor> descriptionBuffer,
|
||||
const GenericArgument *arguments,
|
||||
llvm::ArrayRef<GenericArgument> arguments,
|
||||
Buffer<const GenericValueMetadataPattern> patternBuffer,
|
||||
size_t extraDataSize) {
|
||||
auto *pattern = patternBuffer.ptr;
|
||||
@@ -393,12 +410,16 @@ public:
|
||||
readerWriter.template allocate<FullMetadata<Metadata>>(totalSize);
|
||||
auto metadataOffset = sizeof(typename ValueMetadata::HeaderType);
|
||||
|
||||
ERROR_CHECK(initializeValueMetadataFromPattern(
|
||||
metadataBuffer, metadataOffset, descriptionBuffer, patternBuffer));
|
||||
auto initializeResult = initializeValueMetadataFromPattern(
|
||||
metadataBuffer, metadataOffset, descriptionBuffer, patternBuffer);
|
||||
if (!initializeResult)
|
||||
return *initializeResult.getError();
|
||||
|
||||
// Copy the generic arguments into place.
|
||||
ERROR_CHECK(installGenericArguments(metadataBuffer, metadataOffset,
|
||||
descriptionBuffer, arguments));
|
||||
auto installResult = installGenericArguments(metadataBuffer, metadataOffset,
|
||||
descriptionBuffer, arguments);
|
||||
if (!installResult)
|
||||
return *installResult.getError();
|
||||
|
||||
return ConstructedMetadata{metadataBuffer,
|
||||
static_cast<Size>(metadataOffset)};
|
||||
@@ -416,26 +437,36 @@ public:
|
||||
static_cast<uint32_t>(metadataBuffer.ptr->getKind()));
|
||||
|
||||
auto descriptionBuffer =
|
||||
ERROR_CHECK(metadataBuffer.resolvePointer(&valueMetadata->Description));
|
||||
auto patternBuffer = ERROR_CHECK(descriptionBuffer.resolvePointer(
|
||||
&descriptionBuffer.ptr->getFullGenericContextHeader()
|
||||
.DefaultInstantiationPattern));
|
||||
auto completionFunction = ERROR_CHECK(patternBuffer.resolveFunctionPointer(
|
||||
&patternBuffer.ptr->CompletionFunction));
|
||||
metadataBuffer.resolvePointer(&valueMetadata->Description);
|
||||
if (!descriptionBuffer)
|
||||
return *descriptionBuffer.getError();
|
||||
auto patternBuffer = descriptionBuffer->resolvePointer(
|
||||
&descriptionBuffer->ptr->getFullGenericContextHeader()
|
||||
.DefaultInstantiationPattern);
|
||||
if (!patternBuffer)
|
||||
return *patternBuffer.getError();
|
||||
auto completionFunction = patternBuffer->resolveFunctionPointer(
|
||||
&patternBuffer->ptr->CompletionFunction);
|
||||
if (!completionFunction)
|
||||
return *completionFunction.getError();
|
||||
|
||||
if (completionFunction.isNull()) {
|
||||
if (completionFunction->isNull()) {
|
||||
METADATA_BUILDER_LOG(
|
||||
"Type has no completion function, skipping initialization");
|
||||
return {{}};
|
||||
}
|
||||
|
||||
if (auto structmd = llvm::dyn_cast<StructMetadata>(metadata))
|
||||
ERROR_CHECK(initializeStructMetadata(metadataBuffer, structmd,
|
||||
metadataMangleNode));
|
||||
else if (auto enummd = llvm::dyn_cast<EnumMetadata>(metadata))
|
||||
ERROR_CHECK(
|
||||
initializeEnumMetadata(metadataBuffer, enummd, metadataMangleNode));
|
||||
else
|
||||
if (auto structmd = llvm::dyn_cast<StructMetadata>(metadata)) {
|
||||
auto result = initializeStructMetadata(metadataBuffer, structmd,
|
||||
metadataMangleNode);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
} else if (auto enummd = llvm::dyn_cast<EnumMetadata>(metadata)) {
|
||||
auto result =
|
||||
initializeEnumMetadata(metadataBuffer, enummd, metadataMangleNode);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
} else
|
||||
return BuilderError(
|
||||
"Don't know how to initialize metadata kind %#" PRIx32,
|
||||
static_cast<uint32_t>(metadataBuffer.ptr->getKind()));
|
||||
@@ -455,9 +486,10 @@ public:
|
||||
Buffer<const ValueWitnessTable> from) {
|
||||
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
|
||||
#define VALUE_WITNESS(LOWER_ID, UPPER_ID) \
|
||||
auto LOWER_ID##_Buffer = \
|
||||
ERROR_CHECK(from.resolveFunctionPointer(&from.ptr->LOWER_ID)); \
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->LOWER_ID, LOWER_ID##_Buffer);
|
||||
auto LOWER_ID##_Buffer = from.resolveFunctionPointer(&from.ptr->LOWER_ID); \
|
||||
if (!LOWER_ID##_Buffer) \
|
||||
return *LOWER_ID##_Buffer.getError(); \
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->LOWER_ID, *LOWER_ID##_Buffer);
|
||||
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE)
|
||||
#include "swift/ABI/ValueWitness.def"
|
||||
|
||||
@@ -488,57 +520,99 @@ public:
|
||||
METADATA_BUILDER_LOG("Uncommon layout case, flags.isInlineStorage=%s",
|
||||
flags.isInlineStorage() ? "true" : "false");
|
||||
if (flags.isInlineStorage()) {
|
||||
if (!pod_direct_initializeBufferWithCopyOfBuffer)
|
||||
return *pod_direct_initializeBufferWithCopyOfBuffer.getError();
|
||||
vwtBuffer.writeFunctionPointer(
|
||||
&vwtBuffer.ptr->initializeBufferWithCopyOfBuffer,
|
||||
ERROR_CHECK(pod_direct_initializeBufferWithCopyOfBuffer));
|
||||
*pod_direct_initializeBufferWithCopyOfBuffer);
|
||||
} else {
|
||||
if (!pod_indirect_initializeBufferWithCopyOfBuffer)
|
||||
return *pod_indirect_initializeBufferWithCopyOfBuffer.getError();
|
||||
vwtBuffer.writeFunctionPointer(
|
||||
&vwtBuffer.ptr->initializeBufferWithCopyOfBuffer,
|
||||
ERROR_CHECK(pod_indirect_initializeBufferWithCopyOfBuffer));
|
||||
*pod_indirect_initializeBufferWithCopyOfBuffer);
|
||||
}
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->destroy,
|
||||
ERROR_CHECK(pod_destroy));
|
||||
if (!pod_destroy)
|
||||
return *pod_destroy.getError();
|
||||
if (!pod_copy)
|
||||
return *pod_copy.getError();
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->destroy, *pod_destroy);
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->initializeWithCopy,
|
||||
ERROR_CHECK(pod_copy));
|
||||
*pod_copy);
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->initializeWithTake,
|
||||
ERROR_CHECK(pod_copy));
|
||||
*pod_copy);
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->assignWithCopy,
|
||||
ERROR_CHECK(pod_copy));
|
||||
*pod_copy);
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->assignWithTake,
|
||||
ERROR_CHECK(pod_copy));
|
||||
*pod_copy);
|
||||
// getEnumTagSinglePayload and storeEnumTagSinglePayload are not
|
||||
// interestingly optimizable based on POD-ness.
|
||||
return {{}};
|
||||
|
||||
case sizeWithAlignmentMask(1, 0, 0):
|
||||
case sizeWithAlignmentMask(1, 0, 0): {
|
||||
METADATA_BUILDER_LOG("case sizeWithAlignmentMask(1, 0, 0)");
|
||||
ERROR_CHECK(copyVWT(vwtBuffer, ERROR_CHECK(VWT_Bi8_)));
|
||||
if (!VWT_Bi8_)
|
||||
return *VWT_Bi8_.getError();
|
||||
auto result = copyVWT(vwtBuffer, *VWT_Bi8_);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
break;
|
||||
case sizeWithAlignmentMask(2, 1, 0):
|
||||
}
|
||||
case sizeWithAlignmentMask(2, 1, 0): {
|
||||
if (!VWT_Bi16_)
|
||||
return *VWT_Bi16_.getError();
|
||||
METADATA_BUILDER_LOG("case sizeWithAlignmentMask(2, 1, 0)");
|
||||
ERROR_CHECK(copyVWT(vwtBuffer, ERROR_CHECK(VWT_Bi16_)));
|
||||
auto result = copyVWT(vwtBuffer, *VWT_Bi16_);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
break;
|
||||
case sizeWithAlignmentMask(4, 3, 0):
|
||||
}
|
||||
case sizeWithAlignmentMask(4, 3, 0): {
|
||||
if (!VWT_Bi32_)
|
||||
return *VWT_Bi32_.getError();
|
||||
METADATA_BUILDER_LOG("case sizeWithAlignmentMask(4, 3, 0)");
|
||||
ERROR_CHECK(copyVWT(vwtBuffer, ERROR_CHECK(VWT_Bi32_)));
|
||||
auto result = copyVWT(vwtBuffer, *VWT_Bi32_);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
break;
|
||||
case sizeWithAlignmentMask(8, 7, 0):
|
||||
}
|
||||
case sizeWithAlignmentMask(8, 7, 0): {
|
||||
if (!VWT_Bi64_)
|
||||
return *VWT_Bi64_.getError();
|
||||
METADATA_BUILDER_LOG("case sizeWithAlignmentMask(8, 7, 0)");
|
||||
ERROR_CHECK(copyVWT(vwtBuffer, ERROR_CHECK(VWT_Bi64_)));
|
||||
auto result = copyVWT(vwtBuffer, *VWT_Bi64_);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
break;
|
||||
case sizeWithAlignmentMask(16, 15, 0):
|
||||
}
|
||||
case sizeWithAlignmentMask(16, 15, 0): {
|
||||
if (!VWT_Bi128_)
|
||||
return *VWT_Bi128_.getError();
|
||||
METADATA_BUILDER_LOG("case sizeWithAlignmentMask(16, 15, 0)");
|
||||
ERROR_CHECK(copyVWT(vwtBuffer, ERROR_CHECK(VWT_Bi128_)));
|
||||
auto result = copyVWT(vwtBuffer, *VWT_Bi128_);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
break;
|
||||
case sizeWithAlignmentMask(32, 31, 0):
|
||||
}
|
||||
case sizeWithAlignmentMask(32, 31, 0): {
|
||||
if (!VWT_Bi256_)
|
||||
return *VWT_Bi256_.getError();
|
||||
METADATA_BUILDER_LOG("case sizeWithAlignmentMask(32, 31, 0)");
|
||||
ERROR_CHECK(copyVWT(vwtBuffer, ERROR_CHECK(VWT_Bi256_)));
|
||||
auto result = copyVWT(vwtBuffer, *VWT_Bi256_);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
break;
|
||||
case sizeWithAlignmentMask(64, 63, 0):
|
||||
}
|
||||
case sizeWithAlignmentMask(64, 63, 0): {
|
||||
if (!VWT_Bi512_)
|
||||
return *VWT_Bi512_.getError();
|
||||
METADATA_BUILDER_LOG("case sizeWithAlignmentMask(64, 63, 0)");
|
||||
ERROR_CHECK(copyVWT(vwtBuffer, ERROR_CHECK(VWT_Bi512_)));
|
||||
auto result = copyVWT(vwtBuffer, *VWT_Bi512_);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {{}};
|
||||
}
|
||||
@@ -547,8 +621,10 @@ public:
|
||||
METADATA_BUILDER_LOG(
|
||||
"Is bitwise takable, setting pod_copy as initializeWithTake");
|
||||
// Use POD value witnesses for operations that do an initializeWithTake.
|
||||
if (!pod_copy)
|
||||
return *pod_copy.getError();
|
||||
vwtBuffer.writeFunctionPointer(&vwtBuffer.ptr->initializeWithTake,
|
||||
ERROR_CHECK(pod_copy));
|
||||
*pod_copy);
|
||||
}
|
||||
return {{}};
|
||||
}
|
||||
@@ -561,13 +637,17 @@ public:
|
||||
METADATA_BUILDER_LOG("Initializing struct");
|
||||
|
||||
auto descriptionBuffer =
|
||||
ERROR_CHECK(metadataBuffer.resolvePointer(&metadata->Description));
|
||||
metadataBuffer.resolvePointer(&metadata->Description);
|
||||
if (!descriptionBuffer)
|
||||
return *descriptionBuffer.getError();
|
||||
auto description =
|
||||
reinterpret_cast<const StructDescriptor *>(descriptionBuffer.ptr);
|
||||
reinterpret_cast<const StructDescriptor *>(descriptionBuffer->ptr);
|
||||
|
||||
auto fieldDescriptorBuffer =
|
||||
ERROR_CHECK(descriptionBuffer.resolvePointer(&description->Fields));
|
||||
auto fieldDescriptor = fieldDescriptorBuffer.ptr;
|
||||
descriptionBuffer->resolvePointer(&description->Fields);
|
||||
if (!fieldDescriptorBuffer)
|
||||
return *fieldDescriptorBuffer.getError();
|
||||
auto fieldDescriptor = fieldDescriptorBuffer->ptr;
|
||||
auto fields = fieldDescriptor->getFields();
|
||||
METADATA_BUILDER_LOG("%zu fields", fields.size());
|
||||
|
||||
@@ -587,25 +667,32 @@ public:
|
||||
|
||||
for (unsigned i = 0; i != fields.size(); ++i) {
|
||||
auto &field = fields[i];
|
||||
auto nameBuffer =
|
||||
ERROR_CHECK(fieldDescriptorBuffer.resolvePointer(&field.FieldName));
|
||||
auto mangledTypeNameBuffer = ERROR_CHECK(
|
||||
fieldDescriptorBuffer.resolvePointer(&field.MangledTypeName));
|
||||
auto nameBuffer = fieldDescriptorBuffer->resolvePointer(&field.FieldName);
|
||||
if (!nameBuffer)
|
||||
return *nameBuffer.getError();
|
||||
auto mangledTypeNameBuffer =
|
||||
fieldDescriptorBuffer->resolvePointer(&field.MangledTypeName);
|
||||
if (!mangledTypeNameBuffer)
|
||||
return *mangledTypeNameBuffer.getError();
|
||||
auto mangledTypeName = swift::Demangle::makeSymbolicMangledNameStringRef(
|
||||
mangledTypeNameBuffer.ptr);
|
||||
mangledTypeNameBuffer->ptr);
|
||||
METADATA_BUILDER_LOG(
|
||||
"Examining field %u '%s' type '%.*s' (mangled name is %zu bytes)", i,
|
||||
nameBuffer.ptr, (int)mangledTypeName.size(), mangledTypeName.data(),
|
||||
nameBuffer->ptr, (int)mangledTypeName.size(), mangledTypeName.data(),
|
||||
mangledTypeName.size());
|
||||
|
||||
auto fieldTypeBuffer = ERROR_CHECK(readerWriter.getTypeByMangledName(
|
||||
metadataBuffer, metadataMangleNode, mangledTypeName));
|
||||
auto *fieldType = fieldTypeBuffer.ptr;
|
||||
auto fieldTypeBuffer = readerWriter.getTypeByMangledName(
|
||||
metadataBuffer, metadataMangleNode, mangledTypeName);
|
||||
if (!fieldTypeBuffer)
|
||||
return *fieldTypeBuffer.getError();
|
||||
auto *fieldType = fieldTypeBuffer->ptr;
|
||||
METADATA_BUILDER_LOG("Looked up field type metadata %p", fieldType);
|
||||
|
||||
auto fieldWitnessTableBuffer = ERROR_CHECK(fieldTypeBuffer.resolvePointer(
|
||||
&asFullMetadata(fieldType)->ValueWitnesses));
|
||||
auto *fieldWitnessTable = fieldWitnessTableBuffer.ptr;
|
||||
auto fieldWitnessTableBuffer = fieldTypeBuffer->resolvePointer(
|
||||
&asFullMetadata(fieldType)->ValueWitnesses);
|
||||
if (!fieldWitnessTableBuffer)
|
||||
return *fieldWitnessTableBuffer.getError();
|
||||
auto *fieldWitnessTable = fieldWitnessTableBuffer->ptr;
|
||||
auto *fieldLayout = fieldWitnessTable->getTypeLayout();
|
||||
size = roundUpToAlignMask(size, fieldLayout->flags.getAlignmentMask());
|
||||
|
||||
@@ -637,15 +724,17 @@ public:
|
||||
layout.extraInhabitantCount = extraInhabitantCount;
|
||||
layout.stride = std::max(size_t(1), roundUpToAlignMask(size, alignMask));
|
||||
|
||||
auto oldVWTBuffer = ERROR_CHECK(metadataBuffer.resolvePointer(
|
||||
&asFullMetadata(metadata)->ValueWitnesses));
|
||||
auto *oldVWT = oldVWTBuffer.ptr;
|
||||
auto oldVWTBuffer = metadataBuffer.resolvePointer(
|
||||
&asFullMetadata(metadata)->ValueWitnesses);
|
||||
if (!oldVWTBuffer)
|
||||
return *oldVWTBuffer.getError();
|
||||
auto *oldVWT = oldVWTBuffer->ptr;
|
||||
|
||||
if (readerWriter.isLoggingEnabled()) {
|
||||
auto info = readerWriter.getSymbolInfo(oldVWTBuffer);
|
||||
auto info = readerWriter.getSymbolInfo(*oldVWTBuffer);
|
||||
METADATA_BUILDER_LOG("Initializing new VWT from old VWT %#" PRIx64
|
||||
" - %s (%s + %" PRIu64 ")",
|
||||
oldVWTBuffer.getAddress(), info.symbolName.c_str(),
|
||||
oldVWTBuffer->getAddress(), info.symbolName.c_str(),
|
||||
info.libraryName.c_str(), info.pointerOffset);
|
||||
}
|
||||
|
||||
@@ -662,12 +751,17 @@ public:
|
||||
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE) \
|
||||
// This macro intentionally left blank.
|
||||
#define FUNCTION_VALUE_WITNESS(LOWER_ID, UPPER_ID, RETURN_TYPE, PARAM_TYPES) \
|
||||
newVWTData.writeFunctionPointer( \
|
||||
&newVWT->LOWER_ID, \
|
||||
ERROR_CHECK(oldVWTBuffer.resolveFunctionPointer(&oldVWT->LOWER_ID)));
|
||||
{ \
|
||||
auto fptr = oldVWTBuffer->resolveFunctionPointer(&oldVWT->LOWER_ID); \
|
||||
if (!fptr) \
|
||||
return *fptr.getError(); \
|
||||
newVWTData.writeFunctionPointer(&newVWT->LOWER_ID, *fptr); \
|
||||
}
|
||||
#include "swift/ABI/ValueWitness.def"
|
||||
|
||||
ERROR_CHECK(installCommonValueWitnesses(layout, newVWTData));
|
||||
auto installResult = installCommonValueWitnesses(layout, newVWTData);
|
||||
if (!installResult)
|
||||
return *installResult.getError();
|
||||
|
||||
newVWT->size = layout.size;
|
||||
newVWT->stride = layout.stride;
|
||||
@@ -694,8 +788,8 @@ public:
|
||||
BuilderErrorOr<size_t>
|
||||
extraDataSize(Buffer<const TypeContextDescriptor> descriptionBuffer,
|
||||
Buffer<const GenericMetadataPattern> patternBuffer) {
|
||||
METADATA_BUILDER_LOG("Getting extra data size for %s",
|
||||
ERROR_CHECK(getDescriptorName(descriptionBuffer)));
|
||||
auto name = getDescriptorName(descriptionBuffer);
|
||||
METADATA_BUILDER_LOG("Getting extra data size for %s", *name);
|
||||
|
||||
auto *pattern = patternBuffer.ptr;
|
||||
|
||||
@@ -801,20 +895,31 @@ public:
|
||||
|
||||
auto fullMetadata = asFullMetadata(metadataBuffer.ptr);
|
||||
|
||||
auto valueWitnesses = ERROR_CHECK(
|
||||
metadataBuffer.resolvePointer(&fullMetadata->ValueWitnesses));
|
||||
printPointer(" value witnesses: ", valueWitnesses);
|
||||
ERROR_CHECK(dumpVWT(valueWitnesses));
|
||||
auto valueWitnesses =
|
||||
metadataBuffer.resolvePointer(&fullMetadata->ValueWitnesses);
|
||||
if (!valueWitnesses)
|
||||
return *valueWitnesses.getError();
|
||||
printPointer(" value witnesses: ", *valueWitnesses);
|
||||
auto dumpResult = dumpVWT(*valueWitnesses);
|
||||
if (!dumpResult)
|
||||
return *dumpResult.getError();
|
||||
|
||||
auto kind = fullMetadata->getKind();
|
||||
auto kindString = getStringForMetadataKind(kind);
|
||||
print(" kind: %#" PRIx32 " (%s)\n", static_cast<uint32_t>(kind),
|
||||
kindString.str().c_str());
|
||||
|
||||
if (auto classmd = llvm::dyn_cast<ClassMetadataType>(metadataBuffer.ptr))
|
||||
ERROR_CHECK(dumpClassMetadata(metadataBuffer, classmd));
|
||||
else if (auto valuemd = llvm::dyn_cast<ValueMetadata>(metadataBuffer.ptr))
|
||||
ERROR_CHECK(dumpValueMetadata(metadataBuffer, valuemd));
|
||||
if (auto classmd =
|
||||
llvm::dyn_cast<ClassMetadataType>(metadataBuffer.ptr)) {
|
||||
auto dumpResult = dumpClassMetadata(metadataBuffer, classmd);
|
||||
if (!dumpResult)
|
||||
return *dumpResult.getError();
|
||||
} else if (auto valuemd =
|
||||
llvm::dyn_cast<ValueMetadata>(metadataBuffer.ptr)) {
|
||||
auto dumpResult = dumpValueMetadata(metadataBuffer, valuemd);
|
||||
if (!dumpResult)
|
||||
return *dumpResult.getError();
|
||||
}
|
||||
|
||||
return {{}};
|
||||
}
|
||||
@@ -829,25 +934,36 @@ public:
|
||||
dumpValueMetadata(Buffer<const Metadata> metadataBuffer,
|
||||
const ValueMetadata *metadata) {
|
||||
auto descriptionBuffer =
|
||||
ERROR_CHECK(metadataBuffer.resolvePointer(&metadata->Description));
|
||||
auto description = descriptionBuffer.ptr;
|
||||
printPointer(" description: ", descriptionBuffer);
|
||||
metadataBuffer.resolvePointer(&metadata->Description);
|
||||
if (!descriptionBuffer)
|
||||
return *descriptionBuffer.getError();
|
||||
auto description = descriptionBuffer->ptr;
|
||||
printPointer(" description: ", *descriptionBuffer);
|
||||
|
||||
if (description->hasLayoutString()) {
|
||||
auto layoutStringBuffer = ERROR_CHECK(metadataBuffer.resolvePointer(
|
||||
&asFullMetadata(metadata)->layoutString));
|
||||
printPointer(" layout string: ", layoutStringBuffer);
|
||||
auto layoutStringBuffer = metadataBuffer.resolvePointer(
|
||||
&asFullMetadata(metadata)->layoutString);
|
||||
if (!layoutStringBuffer)
|
||||
return *layoutStringBuffer.getError();
|
||||
printPointer(" layout string: ", *layoutStringBuffer);
|
||||
}
|
||||
|
||||
auto name =
|
||||
ERROR_CHECK(descriptionBuffer.resolvePointer(&description->Name));
|
||||
printPointer(" name: ", name);
|
||||
print(" \"%s\"\n", name.ptr);
|
||||
auto name = descriptionBuffer->resolvePointer(&description->Name);
|
||||
if (!name)
|
||||
return *name.getError();
|
||||
printPointer(" name: ", *name);
|
||||
print(" \"%s\"\n", name->ptr);
|
||||
|
||||
if (auto structmd = llvm::dyn_cast<StructMetadata>(metadataBuffer.ptr))
|
||||
ERROR_CHECK(dumpStructMetadata(metadataBuffer, structmd));
|
||||
else if (auto enummd = llvm::dyn_cast<EnumMetadata>(metadataBuffer.ptr))
|
||||
ERROR_CHECK(dumpEnumMetadata(metadataBuffer, enummd));
|
||||
if (auto structmd = llvm::dyn_cast<StructMetadata>(metadataBuffer.ptr)) {
|
||||
auto dumpResult = dumpStructMetadata(metadataBuffer, structmd);
|
||||
if (!dumpResult)
|
||||
return *dumpResult.getError();
|
||||
} else if (auto enummd =
|
||||
llvm::dyn_cast<EnumMetadata>(metadataBuffer.ptr)) {
|
||||
auto dumpResult = dumpEnumMetadata(metadataBuffer, enummd);
|
||||
if (!dumpResult)
|
||||
return *dumpResult.getError();
|
||||
}
|
||||
|
||||
if (description->isGeneric()) {
|
||||
auto numGenericParams =
|
||||
@@ -856,10 +972,11 @@ public:
|
||||
ConstTargetMetadataPointer<Runtime, swift::TargetMetadata>>(
|
||||
metadata, description->getGenericArgumentOffset());
|
||||
for (unsigned i = 0; i < numGenericParams; i++) {
|
||||
auto arg =
|
||||
ERROR_CHECK(metadataBuffer.resolvePointer(&genericArguments[i]));
|
||||
auto arg = metadataBuffer.resolvePointer(&genericArguments[i]);
|
||||
if (!arg)
|
||||
return *arg.getError();
|
||||
print(" genericArg[%u]: ", i);
|
||||
printPointer(arg);
|
||||
printPointer(*arg);
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
@@ -871,9 +988,11 @@ public:
|
||||
dumpStructMetadata(Buffer<const Metadata> metadataBuffer,
|
||||
const StructMetadata *metadata) {
|
||||
auto descriptionBuffer =
|
||||
ERROR_CHECK(metadataBuffer.resolvePointer(&metadata->Description));
|
||||
metadataBuffer.resolvePointer(&metadata->Description);
|
||||
if (!descriptionBuffer)
|
||||
return *descriptionBuffer.getError();
|
||||
auto structDescription =
|
||||
reinterpret_cast<const StructDescriptor *>(descriptionBuffer.ptr);
|
||||
reinterpret_cast<const StructDescriptor *>(descriptionBuffer->ptr);
|
||||
if (structDescription->hasFieldOffsetVector()) {
|
||||
auto *offsetsStart = wordsOffset<StoredPointer>(
|
||||
metadata, structDescription->FieldOffsetVectorOffset);
|
||||
@@ -888,9 +1007,11 @@ public:
|
||||
dumpEnumMetadata(Buffer<const Metadata> metadataBuffer,
|
||||
const EnumMetadata *metadata) {
|
||||
auto descriptionBuffer =
|
||||
ERROR_CHECK(metadataBuffer.resolvePointer(&metadata->Description));
|
||||
metadataBuffer.resolvePointer(&metadata->Description);
|
||||
if (!descriptionBuffer)
|
||||
return *descriptionBuffer.getError();
|
||||
auto description =
|
||||
reinterpret_cast<const EnumDescriptor *>(descriptionBuffer.ptr);
|
||||
reinterpret_cast<const EnumDescriptor *>(descriptionBuffer->ptr);
|
||||
|
||||
if (description->hasPayloadSizeOffset()) {
|
||||
auto payloadSizeOffset = description->getPayloadSizeOffset();
|
||||
@@ -909,17 +1030,36 @@ public:
|
||||
|
||||
#define WANT_ONLY_REQUIRED_VALUE_WITNESSES
|
||||
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE) \
|
||||
ERROR_CHECK(dumpVWTDataField(#LOWER_ID, vwt->LOWER_ID));
|
||||
{ \
|
||||
auto dumpResult = dumpVWTDataField(#LOWER_ID, vwt->LOWER_ID); \
|
||||
if (!dumpResult) \
|
||||
return *dumpResult.getError(); \
|
||||
}
|
||||
|
||||
#define FUNCTION_VALUE_WITNESS(LOWER_ID, UPPER_ID, RETURN_TYPE, PARAM_TYPES) \
|
||||
ERROR_CHECK(dumpVWTFunctionField(vwtBuffer, #LOWER_ID, &vwt->LOWER_ID));
|
||||
{ \
|
||||
auto dumpResult = \
|
||||
dumpVWTFunctionField(vwtBuffer, #LOWER_ID, &vwt->LOWER_ID); \
|
||||
if (!dumpResult) \
|
||||
return *dumpResult.getError(); \
|
||||
}
|
||||
#include "swift/ABI/ValueWitness.def"
|
||||
|
||||
if (auto *enumVWT = llvm::dyn_cast<EnumValueWitnessTable>(vwt)) {
|
||||
#define WANT_ONLY_ENUM_VALUE_WITNESSES
|
||||
#define DATA_VALUE_WITNESS(LOWER_ID, UPPER_ID, TYPE) \
|
||||
ERROR_CHECK(dumpVWTDataField(#LOWER_ID, enumVWT->LOWER_ID));
|
||||
{ \
|
||||
auto dumpResult = dumpVWTDataField(#LOWER_ID, enumVWT->LOWER_ID); \
|
||||
if (!dumpResult) \
|
||||
return *dumpResult.getError(); \
|
||||
}
|
||||
#define FUNCTION_VALUE_WITNESS(LOWER_ID, UPPER_ID, RETURN_TYPE, PARAM_TYPES) \
|
||||
ERROR_CHECK(dumpVWTFunctionField(vwtBuffer, #LOWER_ID, &enumVWT->LOWER_ID));
|
||||
{ \
|
||||
auto dumpResult = \
|
||||
dumpVWTFunctionField(vwtBuffer, #LOWER_ID, &enumVWT->LOWER_ID); \
|
||||
if (!dumpResult) \
|
||||
return *dumpResult.getError(); \
|
||||
}
|
||||
#include "swift/ABI/ValueWitness.def"
|
||||
}
|
||||
|
||||
@@ -941,9 +1081,11 @@ public:
|
||||
BuilderErrorOr<std::monostate>
|
||||
dumpVWTFunctionField(Buffer<const ValueWitnessTable> vwtBuffer,
|
||||
const char *name, T *ptr) {
|
||||
auto function = ERROR_CHECK(vwtBuffer.resolveFunctionPointer(ptr));
|
||||
auto function = vwtBuffer.resolveFunctionPointer(ptr);
|
||||
if (!function)
|
||||
return *function.getError();
|
||||
print(" %s: ", name);
|
||||
printPointer(function);
|
||||
printPointer(*function);
|
||||
print("\n");
|
||||
|
||||
return {{}};
|
||||
|
||||
54
include/swift/Runtime/LibPrespecialized.h
Normal file
54
include/swift/Runtime/LibPrespecialized.h
Normal file
@@ -0,0 +1,54 @@
|
||||
//===--- LibPrespecialized.h - Interface for prespecializations -*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Interface for interacting with prespecialized metadata library.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_LIB_PRESPECIALIZED_H
|
||||
#define SWIFT_LIB_PRESPECIALIZED_H
|
||||
|
||||
#include "PrebuiltStringMap.h"
|
||||
#include "swift/ABI/Metadata.h"
|
||||
#include "swift/ABI/TargetLayout.h"
|
||||
|
||||
#define LIB_PRESPECIALIZED_TOP_LEVEL_SYMBOL_NAME "_swift_prespecializationsData"
|
||||
|
||||
namespace swift {
|
||||
|
||||
template <typename Runtime>
|
||||
struct LibPrespecializedData {
|
||||
uint32_t majorVersion;
|
||||
uint32_t minorVersion;
|
||||
|
||||
TargetPointer<Runtime, const void> metadataMap;
|
||||
|
||||
static constexpr uint32_t currentMajorVersion = 1;
|
||||
static constexpr uint32_t currentMinorVersion = 1;
|
||||
|
||||
// Helpers for retrieving the metadata map in-process.
|
||||
static bool stringIsNull(const char *str) { return str == nullptr; }
|
||||
|
||||
using MetadataMap = PrebuiltStringMap<const char *, Metadata *, stringIsNull>;
|
||||
|
||||
const MetadataMap *getMetadataMap() const {
|
||||
return reinterpret_cast<const MetadataMap *>(metadataMap);
|
||||
}
|
||||
};
|
||||
|
||||
LibPrespecializedData<InProcess> *getLibPrespecializedData();
|
||||
Metadata *getLibPrespecializedMetadata(const TypeContextDescriptor *description,
|
||||
const void *const *arguments);
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_LIB_PRESPECIALIZED_H
|
||||
181
include/swift/Runtime/PrebuiltStringMap.h
Normal file
181
include/swift/Runtime/PrebuiltStringMap.h
Normal file
@@ -0,0 +1,181 @@
|
||||
//===--- PrebuiltStringMap.h - Statically built string map ------*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_PREBUILT_STRING_MAP_H
|
||||
#define SWIFT_PREBUILT_STRING_MAP_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace swift {
|
||||
|
||||
/// A map that can be pre-built out of process. Uses a fixed hash function with
|
||||
/// no per-process seeding to ensure consistent hashes between builder and user.
|
||||
///
|
||||
/// The elements are tail allocated. `byteSize` can be used to calculate the
|
||||
/// amount of memory needed. The memory must be initialized with all string
|
||||
/// values set to null. StringTy is opaque for insertion, except for using the
|
||||
/// provided stringIsNull function to check for null values.
|
||||
template <typename StringTy, typename ElemTy, bool (*stringIsNull)(StringTy)>
|
||||
struct PrebuiltStringMap {
|
||||
uint64_t arraySize;
|
||||
|
||||
struct ArrayElement {
|
||||
StringTy key;
|
||||
ElemTy value;
|
||||
};
|
||||
|
||||
ArrayElement *array() {
|
||||
uintptr_t start = (uintptr_t)(&arraySize + 1);
|
||||
return (ArrayElement *)start;
|
||||
}
|
||||
|
||||
const ArrayElement *array() const {
|
||||
uintptr_t start = (uintptr_t)(&arraySize + 1);
|
||||
return (ArrayElement *)start;
|
||||
}
|
||||
|
||||
static size_t byteSize(uint64_t arraySize) {
|
||||
return sizeof(PrebuiltStringMap) + sizeof(ArrayElement) * arraySize;
|
||||
}
|
||||
|
||||
/// Construct an empty map. Must be constructed in memory at least as large as
|
||||
/// byteSize(arraySize). The map can hold at most arraySize-1 values.
|
||||
/// Attempting to insert more than that will result in fatal errors when
|
||||
/// inserting or retrieving values.
|
||||
PrebuiltStringMap(uint64_t arraySize) : arraySize(arraySize) {}
|
||||
|
||||
// Based on MurmurHash2
|
||||
uint64_t hash(const void *data, size_t len) {
|
||||
uint64_t magic = 0xc6a4a7935bd1e995ULL;
|
||||
uint64_t salt = 47;
|
||||
|
||||
uint64_t hash = len * magic;
|
||||
|
||||
const uint8_t *cursor = (const uint8_t *)data;
|
||||
const uint8_t *bulkEnd = cursor + (len & ~(sizeof(uint64_t) - 1));
|
||||
size_t remaining = len;
|
||||
|
||||
while (cursor != bulkEnd) {
|
||||
uint64_t value;
|
||||
memcpy(&value, cursor, sizeof(uint64_t));
|
||||
cursor += sizeof(uint64_t);
|
||||
remaining -= sizeof(uint64_t);
|
||||
|
||||
value *= magic;
|
||||
value ^= value >> salt;
|
||||
value *= magic;
|
||||
|
||||
hash ^= value;
|
||||
hash *= magic;
|
||||
}
|
||||
|
||||
// This is never going to be false, but it's comforting.
|
||||
static_assert(sizeof(uint64_t) == 8);
|
||||
|
||||
// Collect the last few bytes.
|
||||
switch (remaining & 7) {
|
||||
case 7:
|
||||
hash ^= (uint64_t)cursor[6] << 48;
|
||||
[[fallthrough]];
|
||||
case 6:
|
||||
hash ^= (uint64_t)cursor[5] << 40;
|
||||
[[fallthrough]];
|
||||
case 5:
|
||||
hash ^= (uint64_t)cursor[4] << 32;
|
||||
[[fallthrough]];
|
||||
case 4:
|
||||
hash ^= (uint64_t)cursor[3] << 24;
|
||||
[[fallthrough]];
|
||||
case 3:
|
||||
hash ^= (uint64_t)cursor[2] << 16;
|
||||
[[fallthrough]];
|
||||
case 2:
|
||||
hash ^= (uint64_t)cursor[1] << 8;
|
||||
[[fallthrough]];
|
||||
case 1:
|
||||
hash ^= (uint64_t)cursor[0];
|
||||
}
|
||||
|
||||
hash *= magic;
|
||||
hash ^= hash >> salt;
|
||||
hash *= magic;
|
||||
hash ^= hash >> salt;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
/// Perform the search portion of an insertion operation. Returns a pointer to
|
||||
/// the element where string is to be inserted. The caller is responsible for
|
||||
/// initializing the element to contain the string/value. It is assumed that
|
||||
/// the key does not already exist in the map. If it does exist, this will
|
||||
/// insert a useless duplicate.
|
||||
ArrayElement *insert(const void *string, size_t len) {
|
||||
uint64_t hashValue = hash(string, len);
|
||||
size_t index = hashValue % arraySize;
|
||||
|
||||
size_t numSearched = 0;
|
||||
while (!stringIsNull(array()[index].key)) {
|
||||
index = index + 1;
|
||||
if (index >= arraySize)
|
||||
index = 0;
|
||||
|
||||
numSearched++;
|
||||
if (numSearched > arraySize) {
|
||||
assert(false &&
|
||||
"Could not find empty element in PrebuiltStringMap::insert");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return &array()[index];
|
||||
}
|
||||
|
||||
ArrayElement *insert(const char *string) {
|
||||
return insert(string, strlen(string));
|
||||
}
|
||||
|
||||
/// Look up the given string in the table. Requires that StringTy be
|
||||
/// `const char *`.
|
||||
ArrayElement *find(const char *toFind) {
|
||||
size_t len = strlen(toFind);
|
||||
uint64_t hashValue = hash(toFind, len);
|
||||
|
||||
size_t index = hashValue % arraySize;
|
||||
|
||||
size_t numSearched = 0;
|
||||
while (const char *key = array()[index].key) {
|
||||
if (strcmp(key, toFind) == 0)
|
||||
return &array()[index];
|
||||
|
||||
index = index + 1;
|
||||
if (index >= arraySize)
|
||||
index = 0;
|
||||
|
||||
numSearched++;
|
||||
if (numSearched > arraySize) {
|
||||
assert(
|
||||
false &&
|
||||
"Could not find match or empty element in PrebuiltStringMap::find");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace swift
|
||||
|
||||
#endif // SWIFT_PREBUILT_STRING_MAP_H
|
||||
@@ -79,3 +79,7 @@ add_subdirectory(StaticMirror)
|
||||
add_subdirectory(SymbolGraphGen)
|
||||
add_subdirectory(SwiftSyntax)
|
||||
add_subdirectory(Threading)
|
||||
|
||||
if(SWIFT_BUILD_EXTERNAL_GENERIC_METADATA_BUILDER)
|
||||
add_subdirectory(ExternalGenericMetadataBuilder)
|
||||
endif()
|
||||
|
||||
@@ -451,6 +451,24 @@ void Node::removeChildAt(unsigned Pos) {
|
||||
}
|
||||
}
|
||||
|
||||
void Node::replaceChild(unsigned Pos, NodePointer Child) {
|
||||
switch (NodePayloadKind) {
|
||||
case PayloadKind::OneChild:
|
||||
assert(Pos == 0);
|
||||
InlineChildren[0] = Child;
|
||||
break;
|
||||
case PayloadKind::TwoChildren:
|
||||
assert(Pos < 2);
|
||||
InlineChildren[Pos] = Child;
|
||||
break;
|
||||
case PayloadKind::ManyChildren:
|
||||
Children.Nodes[Pos] = Child;
|
||||
break;
|
||||
default:
|
||||
assert(false && "cannot remove child");
|
||||
}
|
||||
}
|
||||
|
||||
void Node::reverseChildren(size_t StartingAt) {
|
||||
assert(StartingAt <= getNumChildren());
|
||||
switch (NodePayloadKind) {
|
||||
|
||||
@@ -526,6 +526,8 @@ ManglingError Remangler::mangleAnyNominalType(Node *node, unsigned depth) {
|
||||
return mangleAnyGenericType(node, "XY", depth);
|
||||
case Node::Kind::TypeAlias:
|
||||
return mangleAnyGenericType(node, "a", depth);
|
||||
case Node::Kind::TypeSymbolicReference:
|
||||
return mangleTypeSymbolicReference(node, depth);
|
||||
default:
|
||||
return MANGLING_ERROR(ManglingError::BadNominalTypeKind, node);
|
||||
}
|
||||
@@ -598,6 +600,10 @@ ManglingError Remangler::mangleGenericArgs(Node *node, char &Separator,
|
||||
NodePointer unboundType = node->getChild(0);
|
||||
DEMANGLER_ASSERT(unboundType->getKind() == Node::Kind::Type, node);
|
||||
NodePointer nominalType = unboundType->getChild(0);
|
||||
if (nominalType->getKind() == Node::Kind::TypeSymbolicReference) {
|
||||
NodePointer resolvedUnboundType = Resolver(SymbolicReferenceKind::Context, (const void *)nominalType->getIndex());
|
||||
nominalType = resolvedUnboundType->getChild(0);
|
||||
}
|
||||
NodePointer parentOrModule = nominalType->getChild(0);
|
||||
RETURN_IF_ERROR(mangleGenericArgs(parentOrModule, Separator, depth + 1,
|
||||
fullSubstitutionMap));
|
||||
|
||||
21
lib/ExternalGenericMetadataBuilder/CMakeLists.txt
Normal file
21
lib/ExternalGenericMetadataBuilder/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
add_swift_host_library(swiftGenericMetadataBuilder
|
||||
SHARED
|
||||
ExternalGenericMetadataBuilder.cpp
|
||||
LLVM_LINK_COMPONENTS object support
|
||||
)
|
||||
|
||||
target_include_directories(swiftGenericMetadataBuilder
|
||||
PRIVATE
|
||||
${LLVM_MAIN_INCLUDE_DIR})
|
||||
|
||||
target_link_libraries(swiftGenericMetadataBuilder
|
||||
PRIVATE
|
||||
swiftDemangling)
|
||||
|
||||
swift_install_in_component(TARGETS swiftGenericMetadataBuilder
|
||||
LIBRARY
|
||||
DESTINATION "lib${LLVM_LIBDIR_SUFFIX}"
|
||||
COMPONENT compiler
|
||||
ARCHIVE
|
||||
DESTINATION "lib${LLVM_LIBDIR_SUFFIX}"
|
||||
COMPONENT compiler)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
//===--- ExternalGenericMetadataBuilder.h - Public interface ----*- C++ -*-===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This header declares functions in the libswiftReflection library,
|
||||
/// which provides mechanisms for reflecting heap information in a
|
||||
/// remote Swift process.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SWIFT_EXTERNAL_GENERIC_METADATA_BUILDER_H
|
||||
#define SWIFT_EXTERNAL_GENERIC_METADATA_BUILDER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "swift/shims/Visibility.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct SwiftExternalMetadataBuilder;
|
||||
struct mach_header;
|
||||
|
||||
// Create a builder object with the given platform and architecture name.
|
||||
SWIFT_ATTRIBUTE_FOR_EXPORTS
|
||||
struct SwiftExternalMetadataBuilder *
|
||||
swift_externalMetadataBuilder_create(int platform, const char *arch);
|
||||
|
||||
// Destroy a builder object.
|
||||
SWIFT_ATTRIBUTE_FOR_EXPORTS
|
||||
void swift_externalMetadataBuilder_destroy(
|
||||
struct SwiftExternalMetadataBuilder *);
|
||||
|
||||
// Returns an error string if the dylib could not be added
|
||||
// The builder owns the string, so the caller does not have to free it
|
||||
// The mach_header* is the raw dylib from disk/memory, before the shared cache
|
||||
// builder has created its own copy of it
|
||||
SWIFT_ATTRIBUTE_FOR_EXPORTS
|
||||
const char *swift_externalMetadataBuilder_addDylib(
|
||||
struct SwiftExternalMetadataBuilder *, const char *install_name,
|
||||
const struct mach_header *, uint64_t size);
|
||||
|
||||
SWIFT_ATTRIBUTE_FOR_EXPORTS
|
||||
const char *swift_externalMetadataBuilder_readNamesJSON(
|
||||
struct SwiftExternalMetadataBuilder *, const char *names_json);
|
||||
|
||||
// Returns an error string if the dylib could not be added. The builder owns the
|
||||
// string, so the caller does not have to free it. The string remains valid
|
||||
// until at least the next call to the builder.
|
||||
SWIFT_ATTRIBUTE_FOR_EXPORTS
|
||||
const char *swift_externalMetadataBuilder_buildMetadata(
|
||||
struct SwiftExternalMetadataBuilder *);
|
||||
|
||||
// Get the JSON for the built metadata.
|
||||
SWIFT_ATTRIBUTE_FOR_EXPORTS
|
||||
const char *swift_externalMetadataBuilder_getMetadataJSON(
|
||||
struct SwiftExternalMetadataBuilder *);
|
||||
|
||||
// Convenience function that works with the filesystem and handles everything in
|
||||
// one call.
|
||||
SWIFT_ATTRIBUTE_FOR_EXPORTS
|
||||
int swift_type_metadata_extract(const char *inputPath, // mangled names
|
||||
const char *dylibSearchPath, // images to add
|
||||
const char *arch,
|
||||
const char *outputPath // json output
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SWIFT_EXTERNAL_GENERIC_METADATA_BUILDER_H
|
||||
4
lib/ExternalGenericMetadataBuilder/module.modulemap
Normal file
4
lib/ExternalGenericMetadataBuilder/module.modulemap
Normal file
@@ -0,0 +1,4 @@
|
||||
module ExternalGenericMetadataBuilder {
|
||||
header "ExternalGenericMetadataBuilder.h"
|
||||
export *
|
||||
}
|
||||
@@ -78,7 +78,7 @@ endif()
|
||||
add_subdirectory(Threading)
|
||||
|
||||
# This static library is shared across swiftCore and swiftRemoteInspection
|
||||
if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR)
|
||||
if(SWIFT_BUILD_STDLIB OR SWIFT_BUILD_REMOTE_MIRROR OR SWIFT_BUILD_EXTERNAL_GENERIC_METADATA_BUILDER)
|
||||
# TODO: due to the use of `add_swift_target_library` rather than `add_library`
|
||||
# we cannot use `target_sources` and thus must resort to list manipulations to
|
||||
# adjust the source list.
|
||||
|
||||
@@ -64,6 +64,7 @@ set(swift_runtime_sources
|
||||
SymbolInfo.cpp
|
||||
KeyPaths.cpp
|
||||
KnownMetadata.cpp
|
||||
LibPrespecialized.cpp
|
||||
Metadata.cpp
|
||||
MetadataLookup.cpp
|
||||
Numeric.cpp
|
||||
|
||||
@@ -516,7 +516,7 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
|
||||
#endif
|
||||
|
||||
auto protocolNode =
|
||||
_buildDemanglingForContext(protocol.getSwiftProtocol(), { }, Dem);
|
||||
_buildDemanglingForContext(protocol.getSwiftProtocol(), {}, Dem);
|
||||
if (!protocolNode)
|
||||
return nullptr;
|
||||
|
||||
|
||||
@@ -88,6 +88,12 @@ VARIABLE(SWIFT_DEBUG_VALIDATE_EXTERNAL_GENERIC_METADATA_BUILDER, uint8_t, 0,
|
||||
"unless a validation failure occurs. Level 2 enables full debug "
|
||||
"logging in the builder.")
|
||||
|
||||
VARIABLE(SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED, bool, true,
|
||||
"Enable use of prespecializations library.")
|
||||
|
||||
VARIABLE(SWIFT_DEBUG_LIB_PRESPECIALIZED_PATH, string, "",
|
||||
"A path to a prespecializations library to use at runtime.")
|
||||
|
||||
VARIABLE(SWIFT_ROOT, string, "",
|
||||
"Overrides the root directory of the Swift installation. "
|
||||
"This is used to locate auxiliary files relative to the runtime "
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
using namespace swift;
|
||||
|
||||
#define LOG(fmt, ...) \
|
||||
log(__FILE_NAME__, __LINE__, __func__, fmt __VA_OPT__(, ) __VA_ARGS__)
|
||||
log(METADATA_BUILDER_LOG_FILE_NAME, __LINE__, __func__, fmt, __VA_ARGS__)
|
||||
|
||||
/// A ReaderWriter (as used by GenericMetadataBuilder) that works in-process.
|
||||
/// Pointer writing and pointer resolution are just raw pointer operations. Type
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
|
||||
using Size = typename Runtime::StoredSize;
|
||||
using StoredPointer = typename Runtime::StoredPointer;
|
||||
using GenericArgument = void *;
|
||||
using GenericArgument = const void *;
|
||||
|
||||
/// A typed buffer which wraps a value, or values, of type T.
|
||||
template <typename T>
|
||||
@@ -269,9 +269,9 @@ public:
|
||||
|
||||
bool isLoggingEnabled() { return true; }
|
||||
|
||||
[[gnu::format(printf, 5, 6)]] void log(const char *filename, unsigned line,
|
||||
const char *function, const char *fmt,
|
||||
...) {
|
||||
SWIFT_FORMAT(5, 6)
|
||||
void log(const char *filename, unsigned line, const char *function,
|
||||
const char *fmt, ...) {
|
||||
if (swift::runtime::environment::
|
||||
SWIFT_DEBUG_VALIDATE_EXTERNAL_GENERIC_METADATA_BUILDER() < 2)
|
||||
return;
|
||||
@@ -288,18 +288,17 @@ public:
|
||||
};
|
||||
|
||||
static BuilderErrorOr<ValueMetadata *> allocateGenericValueMetadata(
|
||||
const ValueTypeDescriptor *description, const void *arguments,
|
||||
const ValueTypeDescriptor *description, llvm::ArrayRef<InProcessReaderWriter::GenericArgument> arguments,
|
||||
const GenericValueMetadataPattern *pattern, size_t extraDataSize) {
|
||||
InProcessReaderWriter readerWriter;
|
||||
GenericMetadataBuilder builder{readerWriter};
|
||||
auto result = ERROR_CHECK(builder.buildGenericValueMetadata(
|
||||
{description},
|
||||
reinterpret_cast<const InProcessReaderWriter::GenericArgument *>(
|
||||
arguments),
|
||||
{pattern}, extraDataSize));
|
||||
auto result = builder.buildGenericValueMetadata({description}, arguments,
|
||||
{pattern}, extraDataSize);
|
||||
if (!result)
|
||||
return *result.getError();
|
||||
|
||||
char *base = reinterpret_cast<char *>(result.data.ptr);
|
||||
return reinterpret_cast<ValueMetadata *>(base + result.offset);
|
||||
char *base = reinterpret_cast<char *>(result->data.ptr);
|
||||
return reinterpret_cast<ValueMetadata *>(base + result->offset);
|
||||
}
|
||||
|
||||
static bool initializeGenericValueMetadata(Metadata *metadata) {
|
||||
@@ -324,8 +323,8 @@ genericValueDataExtraSize(const ValueTypeDescriptor *description,
|
||||
return builder.extraDataSize({description}, {pattern});
|
||||
}
|
||||
|
||||
[[gnu::format(printf, 2, 3)]] static void
|
||||
validationLog(bool isValidationFailure, const char *fmt, ...) {
|
||||
SWIFT_FORMAT(2, 3)
|
||||
static void validationLog(bool isValidationFailure, const char *fmt, ...) {
|
||||
if (!isValidationFailure &&
|
||||
swift::runtime::environment::
|
||||
SWIFT_DEBUG_VALIDATE_EXTERNAL_GENERIC_METADATA_BUILDER() < 2)
|
||||
@@ -342,7 +341,7 @@ validationLog(bool isValidationFailure, const char *fmt, ...) {
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
[[gnu::format(printf, 1, 2)]] static void printToStderr(const char *fmt, ...) {
|
||||
SWIFT_FORMAT(1, 2) static void printToStderr(const char *fmt, ...) {
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
@@ -394,7 +393,7 @@ static bool equalVWTs(const ValueWitnessTable *a, const ValueWitnessTable *b) {
|
||||
|
||||
void swift::validateExternalGenericMetadataBuilder(
|
||||
const Metadata *original, const TypeContextDescriptor *description,
|
||||
const void *arguments) {
|
||||
const void * const *arguments) {
|
||||
if (auto valueDescriptor = dyn_cast<ValueTypeDescriptor>(description)) {
|
||||
if (valueDescriptor->isGeneric()) {
|
||||
auto pattern = reinterpret_cast<GenericValueMetadataPattern *>(
|
||||
@@ -407,8 +406,13 @@ void swift::validateExternalGenericMetadataBuilder(
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &genericContext = *description->getGenericContext();
|
||||
const auto &header = genericContext.getGenericContextHeader();
|
||||
auto argsCount = header.NumKeyArguments;
|
||||
llvm::ArrayRef argsArray{arguments, argsCount};
|
||||
|
||||
auto maybeNewMetadata = allocateGenericValueMetadata(
|
||||
valueDescriptor, arguments, pattern, *extraDataSize.getValue());
|
||||
valueDescriptor, argsArray, pattern, *extraDataSize.getValue());
|
||||
if (auto *error = maybeNewMetadata.getError()) {
|
||||
validationLog(false, "error allocating metadata: %s", error->cStr());
|
||||
return;
|
||||
|
||||
109
stdlib/public/runtime/LibPrespecialized.cpp
Normal file
109
stdlib/public/runtime/LibPrespecialized.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
//===--- LibPrespecialized.cpp - Interface for prespecializations----------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/LibPrespecialized.h"
|
||||
#include "swift/Basic/Lazy.h"
|
||||
#include "swift/Runtime/EnvironmentVariables.h"
|
||||
#include "swift/Runtime/Metadata.h"
|
||||
|
||||
#if SWIFT_STDLIB_HAS_DLADDR && __has_include(<dlfcn.h>)
|
||||
#include <dlfcn.h>
|
||||
#define USE_DLOPEN 1
|
||||
#endif
|
||||
|
||||
#if __has_include(<mach-o/dyld_priv.h>)
|
||||
#include <mach-o/dyld_priv.h>
|
||||
#endif
|
||||
|
||||
using namespace swift;
|
||||
|
||||
static LibPrespecializedData<InProcess> *findLibPrespecialized() {
|
||||
if (!runtime::environment::SWIFT_DEBUG_ENABLE_LIB_PRESPECIALIZED())
|
||||
return nullptr;
|
||||
|
||||
void *dataPtr = nullptr;
|
||||
#if USE_DLOPEN
|
||||
auto path = runtime::environment::SWIFT_DEBUG_LIB_PRESPECIALIZED_PATH();
|
||||
if (path && path[0]) {
|
||||
void *handle = dlopen(path, RTLD_LAZY);
|
||||
if (!handle)
|
||||
return nullptr;
|
||||
|
||||
dataPtr = dlsym(handle, LIB_PRESPECIALIZED_TOP_LEVEL_SYMBOL_NAME);
|
||||
}
|
||||
#if DYLD_GET_SWIFT_PRESPECIALIZED_DATA_DEFINED
|
||||
else {
|
||||
// Disable the prespecializations library if anything in the shared cache is
|
||||
// overridden. Eventually we want to be cleverer and only disable the
|
||||
// prespecializations that have been invalidated, but we'll start with the
|
||||
// simplest approach.
|
||||
if (!dyld_shared_cache_some_image_overridden())
|
||||
dataPtr = _dyld_get_swift_prespecialized_data();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!dataPtr)
|
||||
return nullptr;
|
||||
|
||||
auto *data = reinterpret_cast<LibPrespecializedData<InProcess> *>(dataPtr);
|
||||
if (data->majorVersion !=
|
||||
LibPrespecializedData<InProcess>::currentMajorVersion)
|
||||
return nullptr;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
LibPrespecializedData<InProcess> *swift::getLibPrespecializedData() {
|
||||
return SWIFT_LAZY_CONSTANT(findLibPrespecialized());
|
||||
}
|
||||
|
||||
Metadata *
|
||||
swift::getLibPrespecializedMetadata(const TypeContextDescriptor *description,
|
||||
const void *const *arguments) {
|
||||
auto *data = getLibPrespecializedData();
|
||||
if (!data)
|
||||
return nullptr;
|
||||
|
||||
auto *metadataMap = data->getMetadataMap();
|
||||
|
||||
// TODO: This linear search is a stopgap until we work out the right
|
||||
// representation for the string keys.
|
||||
size_t count = metadataMap->arraySize;
|
||||
auto *entries = metadataMap->array();
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (entries[i].key == nullptr)
|
||||
continue;
|
||||
|
||||
Metadata *candidate = entries[i].value;
|
||||
auto *candidateDescription = candidate->getDescription();
|
||||
if (description != candidateDescription)
|
||||
continue;
|
||||
|
||||
auto *candidateArguments = candidate->getGenericArgs();
|
||||
|
||||
bool match = true;
|
||||
|
||||
const auto &genericContext = *description->getGenericContext();
|
||||
const auto &header = genericContext.getGenericContextHeader();
|
||||
for (unsigned param = 0; param < header.NumParams; param++)
|
||||
if (arguments[param] != candidateArguments[param]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (match)
|
||||
return candidate;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/LibPrespecialized.h"
|
||||
#if defined(_WIN32)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
// Avoid defining macro max(), min() which conflict with std::max(), std::min()
|
||||
@@ -366,6 +367,10 @@ namespace {
|
||||
|
||||
AllocationResult allocate(const TypeContextDescriptor *description,
|
||||
const void * const *arguments) {
|
||||
if (auto *prespecialized =
|
||||
getLibPrespecializedMetadata(description, arguments))
|
||||
return {prespecialized, PrivateMetadataState::Complete};
|
||||
|
||||
// Find a pattern. Currently we always use the default pattern.
|
||||
auto &generics = description->getFullGenericContextHeader();
|
||||
auto pattern = generics.DefaultInstantiationPattern.get();
|
||||
|
||||
@@ -221,7 +221,7 @@ _buildDemanglingForSymbolicReference(SymbolicReferenceKind kind,
|
||||
switch (kind) {
|
||||
case SymbolicReferenceKind::Context:
|
||||
return _buildDemanglingForContext(
|
||||
(const ContextDescriptor *)resolvedReference, {}, Dem);
|
||||
(const ContextDescriptor *)resolvedReference, {}, Dem);
|
||||
|
||||
case SymbolicReferenceKind::AccessorFunctionReference:
|
||||
#if SWIFT_PTRAUTH
|
||||
@@ -2259,7 +2259,7 @@ swift_getTypeByMangledNodeImpl(MetadataRequest request, Demangler &demangler,
|
||||
return TypeInfo{MetadataResponse{type, MetadataState::Complete},
|
||||
TypeReferenceOwnership()};
|
||||
}
|
||||
|
||||
|
||||
// TODO: propagate the request down to the builder instead of calling
|
||||
// swift_checkMetadataState after the fact.
|
||||
DecodedMetadataBuilder builder(demangler, substGenericParam,
|
||||
|
||||
@@ -586,7 +586,7 @@ public:
|
||||
|
||||
void validateExternalGenericMetadataBuilder(
|
||||
const Metadata *original, const TypeContextDescriptor *description,
|
||||
const void *arguments);
|
||||
const void * const *arguments);
|
||||
|
||||
Demangle::NodePointer
|
||||
_buildDemanglingForContext(const ContextDescriptor *context,
|
||||
|
||||
@@ -0,0 +1,485 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %target-build-swift -I %swift-lib-dir -I %swift_src_root/lib/ExternalGenericMetadataBuilder -L%swift-lib-dir -lswiftGenericMetadataBuilder -enable-experimental-feature Extern %s -o %t/ExternalMetadataBuilderTest
|
||||
// RUN: %target-codesign %t/ExternalMetadataBuilderTest
|
||||
// RUN: %target-run %t/ExternalMetadataBuilderTest
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: OS=macosx && CPU=arm64
|
||||
|
||||
import ExternalGenericMetadataBuilder
|
||||
import Foundation
|
||||
import StdlibUnittest
|
||||
|
||||
@_extern(c)
|
||||
func swift_getRuntimeLibraryPath() -> UnsafePointer<CChar>?
|
||||
|
||||
let ExternalGenericMetadataBuilderTests = TestSuite("ExternalGenericMetadataBuilder")
|
||||
|
||||
public struct GenericStruct<T, U, V> {
|
||||
var t: T
|
||||
var u: U
|
||||
var v: V
|
||||
var str: String
|
||||
}
|
||||
|
||||
public struct GenericField<T, U> {
|
||||
var field: GenericStruct<T, U, Double>
|
||||
var int: Int
|
||||
}
|
||||
|
||||
ExternalGenericMetadataBuilderTests.test("JSON output") {
|
||||
let builder = swift_externalMetadataBuilder_create(1, "arm64")
|
||||
|
||||
let inputJSON = """
|
||||
{
|
||||
"metadataNames": [
|
||||
{
|
||||
"name" : "\(_mangledTypeName(GenericField<Int8, Int16>.self)!)"
|
||||
},
|
||||
{
|
||||
"name" : "\(_mangledTypeName(Array<Array<Double>>.self)!)"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
let readJSONErrorCStr = swift_externalMetadataBuilder_readNamesJSON(builder, inputJSON);
|
||||
let readJSONError = readJSONErrorCStr.map { String(cString: $0) }
|
||||
expectNil(readJSONError)
|
||||
|
||||
let swiftCorePathCStr = swift_getRuntimeLibraryPath()
|
||||
let swiftCorePath = swiftCorePathCStr.map { String(cString: $0) }
|
||||
expectNotNil(swiftCorePath)
|
||||
|
||||
// Add this executable as well, so we can test our own types.
|
||||
let executablePath = Bundle.main.executablePath
|
||||
|
||||
for machoPath in [swiftCorePath, executablePath] {
|
||||
let url = URL(fileURLWithPath: machoPath!)
|
||||
let data = NSData(contentsOf: url)!
|
||||
|
||||
let machHeader = data.bytes.assumingMemoryBound(to: mach_header.self)
|
||||
let addDylibErrorCStr =
|
||||
swift_externalMetadataBuilder_addDylib(builder,
|
||||
url.lastPathComponent,
|
||||
machHeader,
|
||||
UInt64(data.length));
|
||||
|
||||
let addDylibError = addDylibErrorCStr.map { String(cString: $0) }
|
||||
expectNil(addDylibError)
|
||||
}
|
||||
|
||||
let buildErrorCStr = swift_externalMetadataBuilder_buildMetadata(builder);
|
||||
let buildError = buildErrorCStr.map { String(cString: $0) }
|
||||
expectNil(buildError)
|
||||
|
||||
let outputJSONCStr = swift_externalMetadataBuilder_getMetadataJSON(builder);
|
||||
let outputJSON = outputJSONCStr.map { String(cString: $0) }
|
||||
expectNotNil(outputJSON)
|
||||
|
||||
let outputJSONObject = try! JSONSerialization.jsonObject(with: outputJSON!.data(using: .utf8)!)
|
||||
let expectedJSONObject = try! JSONSerialization.jsonObject(with: expectedJSON.data(using: .utf8)!)
|
||||
|
||||
let outputJSONDictionary = outputJSONObject as? NSDictionary
|
||||
expectNotNil(outputJSONDictionary)
|
||||
let expectedJSONDictionary = expectedJSONObject as? NSDictionary
|
||||
expectNotNil(expectedJSONDictionary)
|
||||
|
||||
// Don't use expectEqual, as it will print the strings on one line with \n
|
||||
// escapes, which is unreadable here.
|
||||
expectTrue(outputJSONDictionary!.isEqual(expectedJSONDictionary),
|
||||
"Output JSON does not match expected:\n\(outputJSON!)")
|
||||
|
||||
swift_externalMetadataBuilder_destroy(builder)
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
|
||||
// Put the expected JSON at the end so it doesn't get in the way of the rest of
|
||||
// the test code. Make it a computed property so we don't fall afoul of weird
|
||||
// global initialization problems with top-level code.
|
||||
var expectedJSON: String {
|
||||
"""
|
||||
{
|
||||
"version": 1,
|
||||
"platform": 1,
|
||||
"platformVersion": "1.0",
|
||||
"arch": "arm64",
|
||||
"installName": "/usr/lib/libswiftPrespecialized.dylib",
|
||||
"atoms": [
|
||||
{
|
||||
"name": "_$s27ExternalMetadataBuilderTest12GenericFieldVys4Int8Vs5Int16VG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"0000000000000000",
|
||||
{
|
||||
"self": true,
|
||||
"target": "___unnamed_atom_1",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"0002000000000000",
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMn",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$ss4Int8VN",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$ss5Int16VN",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"0000000020000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_$s27ExternalMetadataBuilderTest13GenericStructVys4Int8Vs5Int16VSdG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"0000000000000000",
|
||||
{
|
||||
"self": true,
|
||||
"target": "___unnamed_atom_0",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"0002000000000000",
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest13GenericStructVMn",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$ss4Int8VN",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$ss5Int16VN",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$sSdN",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"00000000020000000800000010000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "___unnamed_atom_0",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 1032,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 1376,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 1536,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 1768,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "__swift_pod_copy",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 2200,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 2420,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 2864,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"2000000000000000200000000000000007000300FFFFFF7F"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "___unnamed_atom_1",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 3520,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 3892,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 4052,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 4312,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "__swift_pod_copy",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 4796,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 5044,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "ExternalMetadataBuilderTest",
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa",
|
||||
"addend": 5160,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"2800000000000000280000000000000007000300FFFFFF7F"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_$sSaySdG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"0000000000000000",
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$sBbWV",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"0002000000000000",
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$sSaMn",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$sSdN",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"00000000000000000000000000000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "_$sSaySaySdGG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"0000000000000000",
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$sBbWV",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"0002000000000000",
|
||||
{
|
||||
"target": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"target": "_$sSaMn",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"self": true,
|
||||
"target": "_$sSaySdG",
|
||||
"addend": 16,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"00000000000000000000000000000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "__swift_prespecializedMetadataMap",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"0500000000000000",
|
||||
{
|
||||
"self": true,
|
||||
"target": "__cstring_$s27ExternalMetadataBuilderTest13GenericStructVys4Int8Vs5Int16VSdG",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"self": true,
|
||||
"target": "_$s27ExternalMetadataBuilderTest13GenericStructVys4Int8Vs5Int16VSdG",
|
||||
"addend": 16,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"self": true,
|
||||
"target": "__cstring_$sSaySdG",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"self": true,
|
||||
"target": "_$sSaySdG",
|
||||
"addend": 16,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"self": true,
|
||||
"target": "__cstring_$s27ExternalMetadataBuilderTest12GenericFieldVys4Int8Vs5Int16VG",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"self": true,
|
||||
"target": "_$s27ExternalMetadataBuilderTest12GenericFieldVys4Int8Vs5Int16VG",
|
||||
"addend": 16,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
"00000000000000000000000000000000",
|
||||
{
|
||||
"self": true,
|
||||
"target": "__cstring_$sSaySaySdGG",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
},
|
||||
{
|
||||
"self": true,
|
||||
"target": "_$sSaySaySdGG",
|
||||
"addend": 16,
|
||||
"kind": "ptr64"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "__cstring_$s27ExternalMetadataBuilderTest12GenericFieldVys4Int8Vs5Int16VG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"2473323745787465726E616C4D657461646174614275696C64657254657374313247656E657269634669656C6456797334496E7438567335496E743136564700"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "__cstring_$s27ExternalMetadataBuilderTest13GenericStructVys4Int8Vs5Int16VSdG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"2473323745787465726E616C4D657461646174614275696C64657254657374313347656E6572696353747275637456797334496E7438567335496E7431365653644700"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "__cstring_$sSaySaySdGG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"24735361795361795364474700"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "__cstring_$sSaySdG",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"247353617953644700"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "__swift_prespecializationsData",
|
||||
"contentType": "constData",
|
||||
"contents": [
|
||||
"0100000001000000",
|
||||
{
|
||||
"self": true,
|
||||
"target": "__swift_prespecializedMetadataMap",
|
||||
"addend": 0,
|
||||
"kind": "ptr64"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"dylibs": [
|
||||
{
|
||||
"installName": "/usr/lib/swift/libswiftCore.dylib",
|
||||
"exports": [
|
||||
{
|
||||
"name": "_$sSaMn"
|
||||
},
|
||||
{
|
||||
"name": "_$ss4Int8VN"
|
||||
},
|
||||
{
|
||||
"name": "_$sSdN"
|
||||
},
|
||||
{
|
||||
"name": "_$sBbWV"
|
||||
},
|
||||
{
|
||||
"name": "__swift_pod_copy"
|
||||
},
|
||||
{
|
||||
"name": "_$ss5Int16VN"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"installName": "ExternalMetadataBuilderTest",
|
||||
"exports": [
|
||||
{
|
||||
"name": "_$s27ExternalMetadataBuilderTest12GenericFieldVMa"
|
||||
},
|
||||
{
|
||||
"name": "_$s27ExternalMetadataBuilderTest13GenericStructVMn"
|
||||
},
|
||||
{
|
||||
"name": "_$s27ExternalMetadataBuilderTest12GenericFieldVMn"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
}
|
||||
@@ -107,6 +107,7 @@ if(("${SWIFT_HOST_VARIANT_SDK}" STREQUAL "${SWIFT_PRIMARY_VARIANT_SDK}") AND
|
||||
Enum.cpp
|
||||
ExtendedExistential.cpp
|
||||
Heap.cpp
|
||||
PrebuiltStringMap.cpp
|
||||
Refcounting.cpp
|
||||
Stdlib.cpp
|
||||
StackAllocator.cpp
|
||||
|
||||
55
unittests/runtime/PrebuiltStringMap.cpp
Normal file
55
unittests/runtime/PrebuiltStringMap.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//===--- PrebuiltStringMap.cpp - Unit tests for PrebuiltStringMap ---------===//
|
||||
//
|
||||
// This source file is part of the Swift.org open source project
|
||||
//
|
||||
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
// Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
//
|
||||
// See https://swift.org/LICENSE.txt for license information
|
||||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "swift/Runtime/PrebuiltStringMap.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
static bool stringIsNull(const char *str) { return str == nullptr; }
|
||||
|
||||
TEST(PrebuiltStringMapTest, basic) {
|
||||
unsigned testEntryCount = 1000;
|
||||
|
||||
std::vector<std::pair<std::string, unsigned>> testVector;
|
||||
testVector.reserve(testEntryCount);
|
||||
for (unsigned i = 0; i < testEntryCount; i++) {
|
||||
std::string key;
|
||||
for (unsigned j = 0; j < i; j++)
|
||||
key += std::to_string(j);
|
||||
testVector.push_back({key, i});
|
||||
}
|
||||
|
||||
using Map = swift::PrebuiltStringMap<const char *, unsigned, stringIsNull>;
|
||||
|
||||
unsigned mapSize = testEntryCount * 4 / 3;
|
||||
void *mapAllocation = calloc(1, Map::byteSize(mapSize));
|
||||
Map *map = new (mapAllocation) Map(mapSize);
|
||||
|
||||
for (auto &[key, value] : testVector) {
|
||||
const char *keyCStr = key.c_str();
|
||||
auto *element = map->insert(keyCStr);
|
||||
EXPECT_NE(element, nullptr);
|
||||
|
||||
element->key = keyCStr;
|
||||
element->value = value;
|
||||
}
|
||||
|
||||
for (auto &[key, value] : testVector) {
|
||||
const char *keyCStr = key.c_str();
|
||||
auto *element = map->find(keyCStr);
|
||||
EXPECT_NE(element, nullptr);
|
||||
|
||||
EXPECT_EQ(element->key, key);
|
||||
EXPECT_EQ(element->value, value);
|
||||
}
|
||||
|
||||
free(mapAllocation);
|
||||
}
|
||||
@@ -14,11 +14,11 @@
|
||||
# Buildbots for Darwin OSes
|
||||
#===------------------------------------------------------------------------===#
|
||||
[preset: mixin_buildbot_install_components]
|
||||
swift-install-components=back-deployment;compiler;clang-builtin-headers;libexec;stdlib;sdk-overlay;static-mirror-lib;editor-integration;tools;toolchain-tools;testsuite-tools;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers;
|
||||
swift-install-components=back-deployment;compiler;clang-builtin-headers;libexec;stdlib;sdk-overlay;static-mirror-lib;editor-integration;tools;toolchain-tools;testsuite-tools;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers;swift-external-generic-metadata-builder;swift-external-generic-metadata-builder-headers
|
||||
|
||||
[preset: mixin_buildbot_install_components_with_clang]
|
||||
|
||||
swift-install-components=autolink-driver;back-deployment;compiler;clang-resource-dir-symlink;libexec;stdlib;sdk-overlay;static-mirror-lib;toolchain-tools;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers
|
||||
swift-install-components=autolink-driver;back-deployment;compiler;clang-resource-dir-symlink;libexec;stdlib;sdk-overlay;static-mirror-lib;toolchain-tools;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers;swift-external-generic-metadata-builder;swift-external-generic-metadata-builder-headers
|
||||
llvm-install-components=llvm-ar;llvm-cov;llvm-profdata;IndexStore;clang;clang-resource-headers;compiler-rt;clangd;dsymutil;LTO;clang-features-file
|
||||
|
||||
[preset: mixin_buildbot_trunk_base]
|
||||
@@ -2795,7 +2795,7 @@ darwin-toolchain-display-name=Swift Development Snapshot
|
||||
darwin-toolchain-name=swift-DEVELOPMENT-SNAPSHOT
|
||||
darwin-toolchain-version=3.999.999
|
||||
llvm-install-components=clang;clang-resource-headers;compiler-rt;libclang;libclang-headers;dsymutil;clang-features-file
|
||||
swift-install-components=back-deployment;compiler;clang-builtin-headers;stdlib;libexec;sdk-overlay;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers
|
||||
swift-install-components=back-deployment;compiler;clang-builtin-headers;stdlib;libexec;sdk-overlay;license;sourcekit-xpc-service;swift-remote-mirror;swift-remote-mirror-headers;swift-external-generic-metadata-builder-headers
|
||||
symbols-package=%(symbols_package)s
|
||||
install-symroot=%(install_symroot)s
|
||||
|
||||
|
||||
@@ -147,6 +147,7 @@ KNOWN_SETTINGS=(
|
||||
build-swift-dynamic-stdlib "" "set to 1 to build dynamic variants of the Swift standard library"
|
||||
build-swift-examples "1" "set to 1 to build examples"
|
||||
build-swift-remote-mirror "1" "set to 1 to build the Swift Remote Mirror library"
|
||||
build-swift-external-generic-metadata-builder "1" "set to 1 to build the Swift External Generic Metadata Builder library"
|
||||
build-swift-static-sdk-overlay "" "set to 1 to build static variants of the Swift SDK overlay"
|
||||
build-swift-static-stdlib "" "set to 1 to build static variants of the Swift standard library"
|
||||
build-swift-stdlib-unittest-extra "0" "set to 1 to build optional StdlibUnittest components"
|
||||
@@ -1861,6 +1862,7 @@ for host in "${ALL_HOSTS[@]}"; do
|
||||
-DSWIFT_NATIVE_SWIFT_TOOLS_PATH:STRING="${native_swift_tools_path}"
|
||||
-DSWIFT_INCLUDE_TOOLS:BOOL=$(true_false "${BUILD_SWIFT_TOOLS}")
|
||||
-DSWIFT_BUILD_REMOTE_MIRROR:BOOL=$(true_false "${BUILD_SWIFT_REMOTE_MIRROR}")
|
||||
-DSWIFT_BUILD_EXTERNAL_GENERIC_METADATA_BUILDER:BOOL=$(true_false "${BUILD_SWIFT_EXTERNAL_GENERIC_METADATA_BUILDER}")
|
||||
-DSWIFT_STDLIB_SIL_DEBUGGING:BOOL=$(true_false "${BUILD_SIL_DEBUGGING_STDLIB}")
|
||||
-DSWIFT_CHECK_INCREMENTAL_COMPILATION:BOOL=$(true_false "${CHECK_INCREMENTAL_COMPILATION}")
|
||||
-DSWIFT_ENABLE_ARRAY_COW_CHECKS:BOOL=$(true_false "${ENABLE_ARRAY_COW_CHECKS}")
|
||||
|
||||
@@ -228,6 +228,7 @@ class Builder(object):
|
||||
cmake_args += ["-DSWIFT_BUILD_PERF_TESTSUITE=NO", "-DSWIFT_INCLUDE_DOCS=NO"]
|
||||
cmake_args += [
|
||||
"-DSWIFT_BUILD_REMOTE_MIRROR=FALSE",
|
||||
"-DSWIFT_BUILD_EXTERNAL_GENERIC_METADATA_BUILDER=FALSE",
|
||||
"-DSWIFT_BUILD_DYNAMIC_STDLIB=FALSE",
|
||||
"-DSWIFT_BUILD_STATIC_STDLIB=FALSE",
|
||||
"-DSWIFT_BUILD_DYNAMIC_SDK_OVERLAY=FALSE",
|
||||
|
||||
@@ -1092,6 +1092,10 @@ def create_argument_parser():
|
||||
default=True,
|
||||
help='Build Remote Mirror')
|
||||
|
||||
option('--build-swift-external-generic-metadata-builder', toggle_true,
|
||||
default=True,
|
||||
help='Build External Generic Metadata Builder')
|
||||
|
||||
option('--build-swift-libexec', toggle_true,
|
||||
default=True,
|
||||
help='build auxiliary executables')
|
||||
|
||||
@@ -82,6 +82,7 @@ EXPECTED_DEFAULTS = {
|
||||
'build_swift_dynamic_sdk_overlay': True,
|
||||
'build_swift_dynamic_stdlib': True,
|
||||
'build_swift_inspect': False,
|
||||
'build_swift_external_generic_metadata_builder': True,
|
||||
'build_swift_private_stdlib': True,
|
||||
'build_swift_static_sdk_overlay': False,
|
||||
'build_swift_static_stdlib': False,
|
||||
@@ -575,6 +576,7 @@ EXPECTED_OPTIONS = [
|
||||
EnableOption('--build-swift-stdlib-unicode-data'),
|
||||
EnableOption('--build-swift-libexec'),
|
||||
EnableOption('--build-swift-remote-mirror'),
|
||||
EnableOption('--build-swift-external-generic-metadata-builder'),
|
||||
EnableOption('--cross-compile-append-host-target-to-destdir'),
|
||||
EnableOption('--distcc'),
|
||||
EnableOption('--sccache'),
|
||||
|
||||
@@ -62,6 +62,7 @@ def unrpathize(filename):
|
||||
'libswiftSwiftPrivateLibcExtras.dylib',
|
||||
'libswiftSwiftPrivateThreadExtras.dylib',
|
||||
'libswiftSwiftReflectionTest.dylib',
|
||||
'libswiftGenericMetadataBuilder.dylib',
|
||||
}
|
||||
|
||||
# The output from dyldinfo -dylibs is a line of header followed by one
|
||||
|
||||
@@ -135,6 +135,8 @@ class BuildScriptInvocation(object):
|
||||
'--build-swift-libexec', str(args.build_swift_libexec).lower(),
|
||||
'--swift-enable-backtracing', str(args.swift_enable_backtracing).lower(),
|
||||
'--build-swift-remote-mirror', str(args.build_swift_remote_mirror).lower(),
|
||||
'--build-swift-external-generic-metadata-builder', str(
|
||||
args.build_swift_external_generic_metadata_builder).lower(),
|
||||
]
|
||||
|
||||
# Compute any product specific cmake arguments.
|
||||
|
||||
@@ -85,6 +85,8 @@ class MinimalStdlib(cmake_product.CMakeProduct):
|
||||
'SWIFT_BUILD_DYNAMIC_SDK_OVERLAY:BOOL', 'FALSE')
|
||||
self.cmake_options.define('SWIFT_BUILD_DYNAMIC_STDLIB:BOOL', 'FALSE')
|
||||
self.cmake_options.define('SWIFT_BUILD_REMOTE_MIRROR:BOOL', 'FALSE')
|
||||
self.cmake_options.define(
|
||||
'SWIFT_BUILD_EXTERNAL_GENERIC_METADATA_BUILDER:BOOL', 'FALSE')
|
||||
self.cmake_options.define(
|
||||
'SWIFT_BUILD_RUNTIME_WITH_HOST_COMPILER:BOOL', 'FALSE')
|
||||
self.cmake_options.define(
|
||||
|
||||
Reference in New Issue
Block a user