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:
Mike Ash
2024-01-26 10:50:34 -05:00
committed by GitHub
39 changed files with 3873 additions and 208 deletions

View File

@@ -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.
#

View File

@@ -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.

View File

@@ -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 {

View File

@@ -63,7 +63,8 @@ struct RuntimeTarget<8> {
};
namespace reflection {
class FieldDescriptor;
template <typename Runtime>
class TargetFieldDescriptor;
}
/// In-process native runtime target.

View File

@@ -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;

View File

@@ -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);

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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 {{}};

View 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

View 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

View File

@@ -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()

View File

@@ -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) {

View File

@@ -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));

View 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

View File

@@ -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

View File

@@ -0,0 +1,4 @@
module ExternalGenericMetadataBuilder {
header "ExternalGenericMetadataBuilder.h"
export *
}

View File

@@ -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.

View File

@@ -64,6 +64,7 @@ set(swift_runtime_sources
SymbolInfo.cpp
KeyPaths.cpp
KnownMetadata.cpp
LibPrespecialized.cpp
Metadata.cpp
MetadataLookup.cpp
Numeric.cpp

View File

@@ -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;

View File

@@ -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 "

View File

@@ -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;

View 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;
}

View File

@@ -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();

View File

@@ -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,

View File

@@ -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,

View File

@@ -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"
}
]
}
]
}
"""
}

View File

@@ -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

View 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);
}

View File

@@ -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

View File

@@ -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}")

View File

@@ -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",

View File

@@ -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')

View File

@@ -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'),

View File

@@ -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

View File

@@ -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.

View File

@@ -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(