@@ -77,6 +77,147 @@ class FunctionParam {
77
77
}
78
78
};
79
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
+ };
80
221
81
222
#if SWIFT_OBJC_INTEROP
82
223
// / For a mangled node that refers to an Objective-C class or protocol,
@@ -391,12 +532,11 @@ class TypeDecoder {
391
532
return Builder.createFunctionType (parameters, result, flags);
392
533
}
393
534
case NodeKind::ImplFunctionType: {
394
- // Minimal support for lowered function types. These come up in
395
- // reflection as capture types. For the reflection library's
396
- // purposes, the only part that matters is the convention.
397
- //
398
- // TODO: Do we want to reflect @escaping?
399
- 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;
400
540
401
541
for (unsigned i = 0 ; i < Node->getNumChildren (); i++) {
402
542
auto child = Node->getChild (i);
@@ -407,7 +547,9 @@ class TypeDecoder {
407
547
408
548
if (child->getText () == " @convention(thin)" ) {
409
549
flags =
410
- flags.withConvention (FunctionMetadataConvention::Thin);
550
+ flags.withRepresentation (ImplFunctionRepresentation::Thin);
551
+ } else if (child->getText () == " @callee_guaranteed" ) {
552
+ calleeConvention = ImplParameterConvention::Direct_Guaranteed;
411
553
}
412
554
} else if (child->getKind () == NodeKind::ImplFunctionAttribute) {
413
555
if (!child->hasText ())
@@ -416,24 +558,46 @@ class TypeDecoder {
416
558
StringRef text = child->getText ();
417
559
if (text == " @convention(c)" ) {
418
560
flags =
419
- flags.withConvention (FunctionMetadataConvention ::CFunctionPointer);
561
+ flags.withRepresentation (ImplFunctionRepresentation ::CFunctionPointer);
420
562
} else if (text == " @convention(block)" ) {
421
563
flags =
422
- flags.withConvention (FunctionMetadataConvention ::Block);
564
+ flags.withRepresentation (ImplFunctionRepresentation ::Block);
423
565
}
424
566
} else if (child->getKind () == NodeKind::ImplEscaping) {
425
- 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 ();
426
579
}
427
580
}
428
581
429
- // Completely punt on argument types and results.
430
- std::vector<FunctionParam<BuiltType>> parameters;
431
-
432
- std::vector<BuiltType> elements;
433
- std::string labels;
434
- 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
+ }
435
592
436
- 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);
437
601
}
438
602
439
603
case NodeKind::ArgumentTuple:
@@ -577,6 +741,29 @@ class TypeDecoder {
577
741
}
578
742
579
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
+
580
767
bool decodeMangledTypeDecl (Demangle::NodePointer node,
581
768
BuiltTypeDecl &typeDecl,
582
769
BuiltType &parent,
0 commit comments