1
+ // ===--- MetadataObjectBuilder.h -------------------------------*- C++ -*--===//
2
+ //
3
+ // This source file is part of the Swift.org open source project
4
+ //
5
+ // Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6
+ // Licensed under Apache License v2.0 with Runtime Library Exception
7
+ //
8
+ // See https://swift.org/LICENSE.txt for license information
9
+ // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10
+ //
11
+ // ===----------------------------------------------------------------------===//
12
+ //
13
+ // Defines routines for use with ObjectBuilder that are specifically
14
+ // useful for building metadata objects.
15
+ //
16
+ // ===----------------------------------------------------------------------===//
17
+
18
+ #ifndef METADATA_OBJECT_BUILDER_H
19
+ #define METADATA_OBJECT_BUILDER_H
20
+
21
+ #include " ObjectBuilder.h"
22
+ #include " SpecifierDSL.h"
23
+ #include " swift/ABI/Metadata.h"
24
+ #include < sstream>
25
+ #include < type_traits>
26
+
27
+ namespace swift {
28
+ using namespace specifierDSL ;
29
+
30
+ // / Add a simple ModuleContextDescriptor with the given name.
31
+ inline void addModuleContextDescriptor (AnyObjectBuilder &builder,
32
+ StringRef moduleName) {
33
+ // Context descriptor flags
34
+ auto contextFlags = ContextDescriptorFlags (ContextDescriptorKind::Module,
35
+ /* generic*/ false ,
36
+ /* unique*/ true ,
37
+ /* version*/ 0 ,
38
+ /* kindSpecific*/ 0 );
39
+ builder.add32 (contextFlags.getIntValue ());
40
+
41
+ // Parent
42
+ builder.add32 (0 );
43
+
44
+ // Name
45
+ builder.addRelativeReferenceToString (moduleName);
46
+ }
47
+
48
+ // / Add a simple ProtocolDescriptor with the given base protocols
49
+ // / but no other requirements.
50
+ inline void addProtocolDescriptor (AnyObjectBuilder &builder,
51
+ const ModuleContextDescriptor *module ,
52
+ StringRef protocolName,
53
+ llvm::ArrayRef<ProtocolSpecifier> baseProtocols) {
54
+ // Context descriptor flags
55
+ auto contextFlags = ContextDescriptorFlags (ContextDescriptorKind::Protocol,
56
+ /* generic*/ false ,
57
+ /* unique*/ true ,
58
+ /* version*/ 0 ,
59
+ /* kindSpecific*/ 0 );
60
+ builder.add32 (contextFlags.getIntValue ());
61
+
62
+ // Parent
63
+ builder.addRelativeIndirectReference (module , /* addend*/ 1 );
64
+
65
+ // Name
66
+ builder.addRelativeReferenceToString (protocolName);
67
+
68
+ // NumRequirementsInSignature
69
+ builder.add32 (baseProtocols.size ());
70
+
71
+ // NumRequirements
72
+ builder.add32 (baseProtocols.size ());
73
+
74
+ // Associated type names
75
+ builder.add32 (0 );
76
+
77
+ ObjectRef<const char > selfType;
78
+ if (!baseProtocols.empty ()) {
79
+ auto subbuilder = builder.createSubobject <const char >(/* align*/ 2 );
80
+ mangleGenericParamType (subbuilder, 0 , 0 );
81
+ selfType = subbuilder.ref ();
82
+ }
83
+
84
+ // Requirement signature requirement descriptors
85
+ for (auto &baseProtocol : baseProtocols) {
86
+ addConformanceRequirement (builder, selfType, baseProtocol);
87
+ }
88
+
89
+ // Protocol requirement descriptors
90
+ for (auto baseProtocol : baseProtocols) {
91
+ (void ) baseProtocol; // Requirements don't actually collect specifics here
92
+
93
+ // Flags
94
+ auto flags = ProtocolRequirementFlags (
95
+ ProtocolRequirementFlags::Kind::BaseProtocol);
96
+ builder.add32 (flags.getIntValue ());
97
+
98
+ // Default implementation
99
+ builder.add32 (0 );
100
+ }
101
+ }
102
+
103
+ template <class T >
104
+ class GlobalObjectBuilder {
105
+ ObjectBuilder<T> builder;
106
+ public:
107
+ template <class Fn >
108
+ GlobalObjectBuilder (Fn &&fn) {
109
+ std::forward<Fn>(fn)(builder);
110
+ (void ) builder.finish ();
111
+ }
112
+ const T *get () const { return builder.get (); }
113
+ };
114
+
115
+ // / Build a global object with the given lambda.
116
+ // /
117
+ // / This uses a static local to magically cache and preserve the
118
+ // / global object. This global caching is uniqued by the template
119
+ // / arguments to this function, so callers should not re-use lambdas
120
+ // / for different calls.
121
+ template <class T , class Fn >
122
+ inline const T *buildGlobalObject (Fn &&fn) {
123
+ static const GlobalObjectBuilder<T> builder (std::forward<Fn>(fn));
124
+ return builder.get ();
125
+ }
126
+
127
+ // / Build a global ModuleContextDescriptor with the name returned by the
128
+ // / given lambda.
129
+ // /
130
+ // / This uses a static local to magically cache and preserve the
131
+ // / global object. This global caching is uniqued by the template
132
+ // / arguments to this function, so callers should not re-use lambdas
133
+ // / for different calls.
134
+ template <class Fn >
135
+ inline const ModuleContextDescriptor *
136
+ buildGlobalModuleContextDescriptor (Fn &&fn) {
137
+ static const GlobalObjectBuilder<ModuleContextDescriptor> builder (
138
+ [&](AnyObjectBuilder &builder) {
139
+ addModuleContextDescriptor (builder, std::forward<Fn>(fn)());
140
+ });
141
+ return builder.get ();
142
+ }
143
+
144
+ // / Build a global protocol descriptor for an empty protocol with
145
+ // / the name returned by the given lambda.
146
+ // /
147
+ // / This uses a static local to magically cache and preserve the
148
+ // / global object. This global caching is uniqued by the template
149
+ // / arguments to this function, so callers should not re-use lambdas
150
+ // / for different calls.
151
+ template <class Fn >
152
+ inline const ProtocolDescriptor *
153
+ buildGlobalProtocolDescriptor (const ModuleContextDescriptor *module , Fn &&fn) {
154
+ static const GlobalObjectBuilder<ProtocolDescriptor> builder (
155
+ [&](AnyObjectBuilder &builder) {
156
+ addProtocolDescriptor (builder, module , std::forward<Fn>(fn)(), {});
157
+ });
158
+ return builder.get ();
159
+ }
160
+
161
+ } // end namespace swift
162
+
163
+ #endif
0 commit comments