Skip to content

Commit 249870c

Browse files
committed
[Runtime] Create an external generic metadata builder.
Create a version of the metadata specialization code which is abstracted so that it can work in different contexts, such as building specialized metadata from dylibs on disk rather than from inside a running process. The GenericMetadataBuilder class is templatized on a ReaderWriter. The ReaderWriter abstracts out everything that's different between in-process and external construction of this data. Instead of reading and writing pointers directly, the builder calls the ReaderWriter to resolve and write pointers. The ReaderWriter also handles symbol lookups and looking up other Swift types by name. This is accompanied by a simple implementation of the ReaderWriter which works in-process. The abstracted calls to resolve and write pointers are implemented using standard pointer dereferencing. A new SWIFT_DEBUG_VALIDATE_EXTERNAL_GENERIC_METADATA_BUILDER environment variable uses the in-process ReaderWriter to validate the builder by running it in parallel with the existing metadata builder code in the runtime. When enabled, the GenericMetadataBuilder is used to build a second copy of metadata built by the runtime, and the two are compared to ensure that they match. When this environment variable is not set, the new builder code is inactive. The builder is incomplete, and this initial version only works on structs. Any unsupported type produces an error, and skips the validation. rdar://116592420
1 parent 7787da1 commit 249870c

File tree

13 files changed

+1591
-59
lines changed

13 files changed

+1591
-59
lines changed

include/swift/ABI/ValueWitnessTable.h

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929

3030
namespace swift {
3131

32-
struct TypeLayout;
32+
template <typename Runtime>
33+
struct TargetTypeLayout;
3334
template <class Runtime> struct TargetEnumValueWitnessTable;
3435
template <typename Runtime> struct TargetMetadata;
3536
using Metadata = TargetMetadata<InProcess>;
@@ -120,7 +121,7 @@ class TargetValueWitnessTypes {
120121
// types for the flags enums.
121122
typedef size_t size;
122123
typedef size_t stride;
123-
typedef ValueWitnessFlags flags;
124+
typedef TargetValueWitnessFlags<typename Runtime::StoredSize> flags;
124125
typedef uint32_t extraInhabitantCount;
125126
};
126127

@@ -214,8 +215,8 @@ template <typename Runtime> struct TargetValueWitnessTable {
214215
const TargetEnumValueWitnessTable<Runtime> *_asEVWT() const;
215216

216217
/// Get the type layout record within this value witness table.
217-
const TypeLayout *getTypeLayout() const {
218-
return reinterpret_cast<const TypeLayout *>(&size);
218+
const TargetTypeLayout<Runtime> *getTypeLayout() const {
219+
return reinterpret_cast<const TargetTypeLayout<Runtime> *>(&size);
219220
}
220221

221222
/// Check whether this metadata is complete.
@@ -224,7 +225,7 @@ template <typename Runtime> struct TargetValueWitnessTable {
224225
/// "Publish" the layout of this type to other threads. All other stores
225226
/// to the value witness table (including its extended header) should have
226227
/// happened before this is called.
227-
void publishLayout(const TypeLayout &layout);
228+
void publishLayout(const TargetTypeLayout<Runtime> &layout);
228229
};
229230

230231
/// A value-witness table with enum entry points.
@@ -275,23 +276,27 @@ TargetValueWitnessTable<Runtime>::_asEVWT() const {
275276
/// necessary to perform dependent layout of generic value types. It excludes
276277
/// the value witness functions and includes only the size, alignment,
277278
/// extra inhabitants, and miscellaneous flags about the type.
278-
struct TypeLayout {
279-
ValueWitnessTypes::size size;
280-
ValueWitnessTypes::stride stride;
281-
ValueWitnessTypes::flags flags;
282-
ValueWitnessTypes::extraInhabitantCount extraInhabitantCount;
279+
template <typename Runtime>
280+
struct TargetTypeLayout {
281+
typename TargetValueWitnessTypes<Runtime>::size size;
282+
typename TargetValueWitnessTypes<Runtime>::stride stride;
283+
typename TargetValueWitnessTypes<Runtime>::flags flags;
284+
typename TargetValueWitnessTypes<Runtime>::extraInhabitantCount
285+
extraInhabitantCount;
283286

284287
private:
285288
void _static_assert_layout();
286289
public:
287-
TypeLayout() = default;
288-
constexpr TypeLayout(ValueWitnessTypes::size size,
289-
ValueWitnessTypes::stride stride,
290-
ValueWitnessTypes::flags flags,
291-
ValueWitnessTypes::extraInhabitantCount xiCount)
292-
: size(size), stride(stride), flags(flags), extraInhabitantCount(xiCount) {}
290+
TargetTypeLayout() = default;
291+
constexpr TargetTypeLayout(
292+
typename TargetValueWitnessTypes<Runtime>::size size,
293+
typename TargetValueWitnessTypes<Runtime>::stride stride,
294+
typename TargetValueWitnessTypes<Runtime>::flags flags,
295+
typename TargetValueWitnessTypes<Runtime>::extraInhabitantCount xiCount)
296+
: size(size), stride(stride), flags(flags),
297+
extraInhabitantCount(xiCount) {}
293298

294-
const TypeLayout *getTypeLayout() const { return this; }
299+
const TargetTypeLayout *getTypeLayout() const { return this; }
295300

296301
/// The number of extra inhabitants, that is, bit patterns that do not form
297302
/// valid values of the type, in this type's binary representation.
@@ -303,14 +308,16 @@ struct TypeLayout {
303308
return extraInhabitantCount != 0;
304309
}
305310
};
311+
using TypeLayout = TargetTypeLayout<InProcess>;
306312

307-
inline void TypeLayout::_static_assert_layout() {
308-
#define CHECK_TYPE_LAYOUT_OFFSET(FIELD) \
309-
static_assert(offsetof(ValueWitnessTable, FIELD) \
310-
- offsetof(ValueWitnessTable, size) \
311-
== offsetof(TypeLayout, FIELD), \
312-
"layout of " #FIELD " in TypeLayout doesn't match " \
313-
"value witness table")
313+
template <typename Runtime>
314+
inline void TargetTypeLayout<Runtime>::_static_assert_layout() {
315+
#define CHECK_TYPE_LAYOUT_OFFSET(FIELD) \
316+
static_assert(offsetof(TargetValueWitnessTable<Runtime>, FIELD) - \
317+
offsetof(TargetValueWitnessTable<Runtime>, size) == \
318+
offsetof(TargetTypeLayout<Runtime>, FIELD), \
319+
"layout of " #FIELD " in TypeLayout doesn't match " \
320+
"value witness table")
314321
CHECK_TYPE_LAYOUT_OFFSET(size);
315322
CHECK_TYPE_LAYOUT_OFFSET(flags);
316323
CHECK_TYPE_LAYOUT_OFFSET(extraInhabitantCount);

include/swift/Demangling/TypeLookupError.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,13 @@ class TypeLookupError {
153153
/// Get the error string from the error value. The value must be passed to
154154
/// `freeErrorString` when done. (Unless you're just calling a `fatalError`
155155
/// in which case there's no point.)
156-
char *copyErrorString() {
156+
char *copyErrorString() const {
157157
return reinterpret_cast<char *>(
158158
Fn(Context, Command::CopyErrorString, nullptr));
159159
}
160160

161161
/// Free an error string previously obtained from `copyErrorString`.
162-
void freeErrorString(char *str) {
162+
void freeErrorString(char *str) const {
163163
Fn(Context, Command::DestroyErrorString, str);
164164
}
165165
};

include/swift/Remote/MetadataReader.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/Demangling/TypeDecoder.h"
2525
#include "swift/Basic/Defer.h"
2626
#include "swift/Basic/ExternalUnion.h"
27+
#include "swift/Basic/MathUtils.h"
2728
#include "swift/Basic/Range.h"
2829
#include "swift/Basic/LLVM.h"
2930
#include "swift/ABI/TypeIdentity.h"
@@ -3419,11 +3420,6 @@ class MetadataReader {
34193420

34203421
return finish(TaggedPointerEncodingKind::Extended);
34213422
}
3422-
3423-
template <class T>
3424-
static constexpr T roundUpToAlignment(T offset, T alignment) {
3425-
return (offset + alignment - 1) & ~(alignment - 1);
3426-
}
34273423
};
34283424

34293425
} // end namespace remote

include/swift/Runtime/Enum.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ using Metadata = TargetMetadata<InProcess>;
3232

3333
template <typename Runtime> struct TargetEnumMetadata;
3434
using EnumMetadata = TargetEnumMetadata<InProcess>;
35-
struct TypeLayout;
35+
template <typename Runtime>
36+
struct TargetTypeLayout;
37+
using TypeLayout = TargetTypeLayout<InProcess>;
3638

3739
/// Initialize the type metadata for a single-case enum type.
3840
///

0 commit comments

Comments
 (0)