28
28
namespace swift {
29
29
namespace Demangle {
30
30
31
- // / Strip generic arguments from the "spine" of a context node, producing a
32
- // / bare context to be used in (e.g.) forming nominal type descriptors.
33
- NodePointer stripGenericArgsFromContextNode (NodePointer node,
34
- NodeFactory &factory);
31
+ enum class ImplMetatypeRepresentation {
32
+ Thin,
33
+ Thick,
34
+ ObjC,
35
+ };
35
36
36
37
// / Describe a function parameter, parameterized on the type
37
38
// / representation.
@@ -76,6 +77,147 @@ class FunctionParam {
76
77
}
77
78
};
78
79
80
+ enum class ImplParameterConvention {
81
+ Indirect_In,
82
+ Indirect_In_Constant,
83
+ Indirect_In_Guaranteed,
84
+ Indirect_Inout,
85
+ Indirect_InoutAliasable,
86
+ Direct_Owned,
87
+ Direct_Unowned,
88
+ Direct_Guaranteed,
89
+ };
90
+
91
+ // / Describe a lowered function parameter, parameterized on the type
92
+ // / representation.
93
+ template <typename BuiltType>
94
+ class ImplFunctionParam {
95
+ ImplParameterConvention Convention;
96
+ BuiltType Type;
97
+
98
+ public:
99
+ using ConventionType = ImplParameterConvention;
100
+
101
+ static Optional<ConventionType>
102
+ getConventionFromString (StringRef conventionString) {
103
+ if (conventionString == " @in" )
104
+ return ConventionType::Indirect_In;
105
+ if (conventionString == " @indirect_in_constant" )
106
+ return ConventionType::Indirect_In_Constant;
107
+ if (conventionString == " @in_guaranteed" )
108
+ return ConventionType::Indirect_In_Guaranteed;
109
+ if (conventionString == " @inout" )
110
+ return ConventionType::Indirect_Inout;
111
+ if (conventionString == " @inout_aliasable" )
112
+ return ConventionType::Indirect_InoutAliasable;
113
+ if (conventionString == " @owned" )
114
+ return ConventionType::Direct_Owned;
115
+ if (conventionString == " @unowned" )
116
+ return ConventionType::Direct_Unowned;
117
+ if (conventionString == " @guaranteed" )
118
+ return ConventionType::Direct_Guaranteed;
119
+
120
+ return None;
121
+ }
122
+
123
+ ImplFunctionParam (ImplParameterConvention convention, BuiltType type)
124
+ : Convention(convention), Type(type) {}
125
+
126
+ ImplParameterConvention getConvention () const { return Convention; }
127
+
128
+ BuiltType getType () const { return Type; }
129
+ };
130
+
131
+ enum class ImplResultConvention {
132
+ Indirect,
133
+ Owned,
134
+ Unowned,
135
+ UnownedInnerPointer,
136
+ Autoreleased,
137
+ };
138
+
139
+ // / Describe a lowered function result, parameterized on the type
140
+ // / representation.
141
+ template <typename BuiltType>
142
+ class ImplFunctionResult {
143
+ ImplResultConvention Convention;
144
+ BuiltType Type;
145
+
146
+ public:
147
+ using ConventionType = ImplResultConvention;
148
+
149
+ static Optional<ConventionType>
150
+ getConventionFromString (StringRef conventionString) {
151
+ if (conventionString == " @out" )
152
+ return ConventionType::Indirect;
153
+ if (conventionString == " @owned" )
154
+ return ConventionType::Owned;
155
+ if (conventionString == " @unowned" )
156
+ return ConventionType::Unowned;
157
+ if (conventionString == " @unowned_inner_pointer" )
158
+ return ConventionType::UnownedInnerPointer;
159
+ if (conventionString == " @autoreleased" )
160
+ return ConventionType::Autoreleased;
161
+
162
+ return None;
163
+ }
164
+
165
+ ImplFunctionResult (ImplResultConvention convention, BuiltType type)
166
+ : Convention(convention), Type(type) {}
167
+
168
+ ImplResultConvention getConvention () const { return Convention; }
169
+
170
+ BuiltType getType () const { return Type; }
171
+ };
172
+
173
+ enum class ImplFunctionRepresentation {
174
+ Thick,
175
+ Block,
176
+ Thin,
177
+ CFunctionPointer,
178
+ Method,
179
+ ObjCMethod,
180
+ WitnessMethod,
181
+ Closure
182
+ };
183
+
184
+ class ImplFunctionTypeFlags {
185
+ unsigned Rep : 3 ;
186
+ unsigned Pseudogeneric : 1 ;
187
+ unsigned Escaping : 1 ;
188
+
189
+ public:
190
+ ImplFunctionTypeFlags () : Rep(0 ), Pseudogeneric(0 ), Escaping(0 ) {}
191
+
192
+ ImplFunctionTypeFlags (ImplFunctionRepresentation rep,
193
+ bool pseudogeneric, bool noescape)
194
+ : Rep(unsigned (rep)), Pseudogeneric(pseudogeneric), Escaping(noescape) {}
195
+
196
+ ImplFunctionTypeFlags
197
+ withRepresentation (ImplFunctionRepresentation rep) const {
198
+ return ImplFunctionTypeFlags (rep, Pseudogeneric, Escaping);
199
+ }
200
+
201
+ ImplFunctionTypeFlags
202
+ withEscaping () const {
203
+ return ImplFunctionTypeFlags (ImplFunctionRepresentation (Rep),
204
+ Pseudogeneric, true );
205
+ }
206
+
207
+ ImplFunctionTypeFlags
208
+ withPseudogeneric () const {
209
+ return ImplFunctionTypeFlags (ImplFunctionRepresentation (Rep),
210
+ true , Escaping);
211
+ }
212
+
213
+ ImplFunctionRepresentation getRepresentation () const {
214
+ return ImplFunctionRepresentation (Rep);
215
+ }
216
+
217
+ bool isEscaping () const { return Escaping; }
218
+
219
+ bool isPseudogeneric () const { return Pseudogeneric; }
220
+ };
79
221
80
222
#if SWIFT_OBJC_INTEROP
81
223
// / For a mangled node that refers to an Objective-C class or protocol,
@@ -248,18 +390,22 @@ class TypeDecoder {
248
390
case NodeKind::Metatype:
249
391
case NodeKind::ExistentialMetatype: {
250
392
unsigned i = 0 ;
251
- bool wasAbstract = false ;
393
+ Optional<ImplMetatypeRepresentation> repr ;
252
394
253
395
// Handle lowered metatypes in a hackish way. If the representation
254
396
// was not thin, force the resulting typeref to have a non-empty
255
397
// representation.
256
398
if (Node->getNumChildren () >= 2 ) {
257
- auto repr = Node->getChild (i++);
258
- if (repr ->getKind () != NodeKind::MetatypeRepresentation ||
259
- !repr ->hasText ())
399
+ auto reprNode = Node->getChild (i++);
400
+ if (reprNode ->getKind () != NodeKind::MetatypeRepresentation ||
401
+ !reprNode ->hasText ())
260
402
return BuiltType ();
261
- if (repr->getText () != " @thin" )
262
- wasAbstract = true ;
403
+ if (reprNode->getText () == " @thin" )
404
+ repr = ImplMetatypeRepresentation::Thin;
405
+ else if (reprNode->getText () == " @thick" )
406
+ repr = ImplMetatypeRepresentation::Thick;
407
+ else if (reprNode->getText () == " @objc_metatype" )
408
+ repr = ImplMetatypeRepresentation::ObjC;
263
409
} else if (Node->getNumChildren () < 1 ) {
264
410
return BuiltType ();
265
411
}
@@ -268,11 +414,9 @@ class TypeDecoder {
268
414
if (!instance)
269
415
return BuiltType ();
270
416
if (Node->getKind () == NodeKind::Metatype) {
271
- return Builder.createMetatypeType (instance, wasAbstract );
417
+ return Builder.createMetatypeType (instance, repr );
272
418
} else if (Node->getKind () == NodeKind::ExistentialMetatype) {
273
- // FIXME: Ignore representation of existential metatype
274
- // completely for now
275
- return Builder.createExistentialMetatypeType (instance);
419
+ return Builder.createExistentialMetatypeType (instance, repr);
276
420
} else {
277
421
assert (false );
278
422
return nullptr ;
@@ -388,12 +532,11 @@ class TypeDecoder {
388
532
return Builder.createFunctionType (parameters, result, flags);
389
533
}
390
534
case NodeKind::ImplFunctionType: {
391
- // Minimal support for lowered function types. These come up in
392
- // reflection as capture types. For the reflection library's
393
- // purposes, the only part that matters is the convention.
394
- //
395
- // TODO: Do we want to reflect @escaping?
396
- FunctionTypeFlags flags;
535
+ auto calleeConvention = ImplParameterConvention::Direct_Unowned;
536
+ std::vector<ImplFunctionParam<BuiltType>> parameters;
537
+ std::vector<ImplFunctionResult<BuiltType>> results;
538
+ std::vector<ImplFunctionResult<BuiltType>> errorResults;
539
+ ImplFunctionTypeFlags flags;
397
540
398
541
for (unsigned i = 0 ; i < Node->getNumChildren (); i++) {
399
542
auto child = Node->getChild (i);
@@ -404,7 +547,9 @@ class TypeDecoder {
404
547
405
548
if (child->getText () == " @convention(thin)" ) {
406
549
flags =
407
- flags.withConvention (FunctionMetadataConvention::Thin);
550
+ flags.withRepresentation (ImplFunctionRepresentation::Thin);
551
+ } else if (child->getText () == " @callee_guaranteed" ) {
552
+ calleeConvention = ImplParameterConvention::Direct_Guaranteed;
408
553
}
409
554
} else if (child->getKind () == NodeKind::ImplFunctionAttribute) {
410
555
if (!child->hasText ())
@@ -413,24 +558,46 @@ class TypeDecoder {
413
558
StringRef text = child->getText ();
414
559
if (text == " @convention(c)" ) {
415
560
flags =
416
- flags.withConvention (FunctionMetadataConvention ::CFunctionPointer);
561
+ flags.withRepresentation (ImplFunctionRepresentation ::CFunctionPointer);
417
562
} else if (text == " @convention(block)" ) {
418
563
flags =
419
- flags.withConvention (FunctionMetadataConvention ::Block);
564
+ flags.withRepresentation (ImplFunctionRepresentation ::Block);
420
565
}
421
566
} else if (child->getKind () == NodeKind::ImplEscaping) {
422
- flags = flags.withEscaping (true );
567
+ flags = flags.withEscaping ();
568
+ } else if (child->getKind () == NodeKind::ImplParameter) {
569
+ if (decodeImplFunctionPart (child, parameters))
570
+ return BuiltType ();
571
+ } else if (child->getKind () == NodeKind::ImplResult) {
572
+ if (decodeImplFunctionPart (child, results))
573
+ return BuiltType ();
574
+ } else if (child->getKind () == NodeKind::ImplErrorResult) {
575
+ if (decodeImplFunctionPart (child, errorResults))
576
+ return BuiltType ();
577
+ } else {
578
+ return BuiltType ();
423
579
}
424
580
}
425
581
426
- // Completely punt on argument types and results.
427
- std::vector<FunctionParam<BuiltType>> parameters;
428
-
429
- std::vector<BuiltType> elements;
430
- std::string labels;
431
- auto result = Builder.createTupleType (elements, std::move (labels), false );
582
+ Optional<ImplFunctionResult<BuiltType>> errorResult;
583
+ switch (errorResults.size ()) {
584
+ case 0 :
585
+ break ;
586
+ case 1 :
587
+ errorResult = errorResults.front ();
588
+ break ;
589
+ default :
590
+ return BuiltType ();
591
+ }
432
592
433
- return Builder.createFunctionType (parameters, result, flags);
593
+ // TODO: Some cases not handled above, but *probably* they cannot
594
+ // appear as the types of values in SIL (yet?):
595
+ // - functions with yield returns
596
+ // - functions with generic signatures
597
+ // - foreign error conventions
598
+ return Builder.createImplFunctionType (calleeConvention,
599
+ parameters, results,
600
+ errorResult, flags);
434
601
}
435
602
436
603
case NodeKind::ArgumentTuple:
@@ -574,6 +741,29 @@ class TypeDecoder {
574
741
}
575
742
576
743
private:
744
+ template <typename T>
745
+ bool decodeImplFunctionPart (Demangle::NodePointer node,
746
+ std::vector<T> &results) {
747
+ if (node->getNumChildren () != 2 )
748
+ return true ;
749
+
750
+ if (node->getChild (0 )->getKind () != Node::Kind::ImplConvention ||
751
+ node->getChild (1 )->getKind () != Node::Kind::Type)
752
+ return true ;
753
+
754
+ StringRef conventionString = node->getChild (0 )->getText ();
755
+ Optional<typename T::ConventionType> convention =
756
+ T::getConventionFromString (conventionString);
757
+ if (!convention)
758
+ return true ;
759
+ BuiltType type = decodeMangledType (node->getChild (1 ));
760
+ if (!type)
761
+ return true ;
762
+
763
+ results.emplace_back (*convention, type);
764
+ return false ;
765
+ }
766
+
577
767
bool decodeMangledTypeDecl (Demangle::NodePointer node,
578
768
BuiltTypeDecl &typeDecl,
579
769
BuiltType &parent,
@@ -611,8 +801,7 @@ class TypeDecoder {
611
801
parent = decodeMangledType (parentContext);
612
802
// Remove any generic arguments from the context node, producing a
613
803
// node that references the nominal type declaration.
614
- declNode =
615
- stripGenericArgsFromContextNode (node, Builder.getNodeFactory ());
804
+ declNode = Demangle::getUnspecialized (node, Builder.getNodeFactory ());
616
805
break ;
617
806
}
618
807
}
0 commit comments