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