@@ -30,6 +30,13 @@ static const ProtocolDescriptor *getEquatableDescriptor() {
30
30
return descriptor;
31
31
}
32
32
33
+ static const ProtocolDescriptor *getComparableDescriptor () {
34
+ auto descriptor = SWIFT_LAZY_CONSTANT (
35
+ reinterpret_cast <const ProtocolDescriptor *>(
36
+ dlsym (RTLD_DEFAULT, " $sSLMp" )));
37
+ return descriptor;
38
+ }
39
+
33
40
static const WitnessTable *conformsToProtocol (const Metadata *type,
34
41
const ProtocolDescriptor *protocol) {
35
42
using Fn = const WitnessTable *(const Metadata *, const ProtocolDescriptor *);
@@ -39,6 +46,21 @@ static const WitnessTable *conformsToProtocol(const Metadata *type,
39
46
return func (type, protocol);
40
47
}
41
48
49
+ template <unsigned int NumWitnesses>
50
+ struct _WitnessTable {
51
+ const ProtocolConformanceDescriptor *Conformance;
52
+ const void *Witnesses[NumWitnesses];
53
+ };
54
+
55
+ using StaticInfixWitness = SWIFT_CC(swift) bool (OpaqueValue *, OpaqueValue *,
56
+ SWIFT_CONTEXT const Metadata *,
57
+ const Metadata *,
58
+ const WitnessTable *);
59
+
60
+ // ===----------------------------------------------------------------------===//
61
+ // Tuple Equatable Conformance
62
+ // ===----------------------------------------------------------------------===//
63
+
42
64
#define TUPLE_EQUATABLE_WT SYMBOL (" _swift_tupleEquatable_wt" )
43
65
44
66
// Define the conformance descriptor for tuple Equatable. We do this in
@@ -66,7 +88,7 @@ extern const ProtocolConformanceDescriptor _swift_tupleEquatable_conf;
66
88
// dependency to libswiftCore (which is where the Equatable protocol desciptor
67
89
// lives), we have to manually implant this before calling any user code.
68
90
__attribute__ ((constructor))
69
- void _emplaceEquatableDescriptor () {
91
+ void _emplaceTupleEquatableDescriptor () {
70
92
auto tupleEquatableConf = const_cast <int32_t *>(
71
93
reinterpret_cast <const int32_t *>(&_swift_tupleEquatable_conf));
72
94
auto equatable = getEquatableDescriptor ();
@@ -75,12 +97,6 @@ void _emplaceEquatableDescriptor() {
75
97
*tupleEquatableConf = intptr_t (equatable) - intptr_t (tupleEquatableConf);
76
98
}
77
99
78
- template <unsigned int NumWitnesses>
79
- struct _WitnessTable {
80
- const ProtocolConformanceDescriptor *Conformance;
81
- const void *Witnesses[NumWitnesses];
82
- };
83
-
84
100
SWIFT_RUNTIME_EXPORT
85
101
const _WitnessTable<1 > _swift_tupleEquatable_wt = {
86
102
&_swift_tupleEquatable_conf,
@@ -119,10 +135,7 @@ bool swift::_swift_tupleEquatable_equals(OpaqueValue *tuple1,
119
135
// Grab the specific witness for this element type.
120
136
auto equatableTable = reinterpret_cast <void * const *>(conformance);
121
137
auto equalsWitness = equatableTable[WitnessTableFirstRequirementOffset];
122
- using Fn = SWIFT_CC (swift) bool (OpaqueValue *, OpaqueValue *,
123
- SWIFT_CONTEXT const Metadata *,
124
- const Metadata *, const WitnessTable *);
125
- auto equals = reinterpret_cast <Fn *>(equalsWitness);
138
+ auto equals = reinterpret_cast <StaticInfixWitness *>(equalsWitness);
126
139
127
140
// Call the equal function.
128
141
auto result = equals (value1, value2, elt.Type , elt.Type , conformance);
@@ -135,3 +148,304 @@ bool swift::_swift_tupleEquatable_equals(OpaqueValue *tuple1,
135
148
// Otherwise this tuple has value equality with all elements.
136
149
return true ;
137
150
}
151
+
152
+ // ===----------------------------------------------------------------------===//
153
+ // Tuple Comparable Conformance
154
+ // ===----------------------------------------------------------------------===//
155
+
156
+ #define TUPLE_COMPARABLE_WT SYMBOL (" _swift_tupleComparable_wt" )
157
+
158
+ // Define the conformance descriptor for tuple Comparable. We do this in
159
+ // assembly to work around relative reference issues.
160
+ __asm(
161
+ " .section __DATA,__data\n "
162
+ " .globl " TUPLE_COMPARABLE_CONF " \n "
163
+ " .p2align 2\n "
164
+ TUPLE_COMPARABLE_CONF " :\n "
165
+ // This is an indirectable relative reference to the Comparable protocol
166
+ // descriptor. However, this is 0 here because the compatibility libraries
167
+ // can't have a dependency on libswiftCore (which is where Comparable lives).
168
+ " .long 0\n "
169
+ // 769 is the MetadataKind::Tuple
170
+ " .long 769\n "
171
+ // This is a direct relative reference to the witness table defined below.
172
+ " .long ((" TUPLE_COMPARABLE_WT " ) - (" TUPLE_COMPARABLE_CONF " )) - 8\n "
173
+ // 32 are the ConformanceFlags with the type reference bit set to MetadataKind.
174
+ " .long 32\n "
175
+ );
176
+
177
+ extern const ProtocolConformanceDescriptor _swift_tupleComparable_conf;
178
+
179
+ // Due to the fact that the compatibility libraries can't have a hard
180
+ // dependency to libswiftCore (which is where the Comparable protocol desciptor
181
+ // lives), we have to manually implant this before calling any user code.
182
+ __attribute__ ((constructor))
183
+ void _emplaceTupleComparableDescriptor() {
184
+ auto tupleComparableConf = const_cast <int32_t *>(
185
+ reinterpret_cast <const int32_t *>(&_swift_tupleComparable_conf));
186
+ auto comparable = getComparableDescriptor ();
187
+
188
+ // This is an indirectable pointer.
189
+ *tupleComparableConf = intptr_t (comparable) - intptr_t (tupleComparableConf);
190
+ }
191
+
192
+ // The base Equatable protocol is itself a requirement, thus the requirement
193
+ // count is 5 (Equatable + 4 operators) and the witness is the tuple Equatable
194
+ // table.
195
+ SWIFT_RUNTIME_EXPORT
196
+ const _WitnessTable<5 > _swift_tupleComparable_wt = {
197
+ &_swift_tupleComparable_conf,
198
+ {
199
+ reinterpret_cast <const void *>(&_swift_tupleEquatable_wt),
200
+ reinterpret_cast <void *>(_swift_tupleComparable_lessThan),
201
+ reinterpret_cast <void *>(_swift_tupleComparable_lessThanOrEqual),
202
+ reinterpret_cast <void *>(_swift_tupleComparable_greaterThanOrEqual),
203
+ reinterpret_cast <void *>(_swift_tupleComparable_greaterThan)
204
+ }
205
+ };
206
+
207
+ SWIFT_RUNTIME_EXPORT SWIFT_CC (swift)
208
+ bool swift::_swift_tupleComparable_lessThan(OpaqueValue *tuple1,
209
+ OpaqueValue *tuple2,
210
+ SWIFT_CONTEXT Metadata *swiftSelf,
211
+ Metadata *Self, void *witnessTable) {
212
+ auto tuple = cast<TupleTypeMetadata>(Self);
213
+
214
+ // Loop through all elements, and check if both tuples element is equal.
215
+ for (size_t i = 0 ; i != tuple->NumElements ; i += 1 ) {
216
+ auto elt = tuple->getElement (i);
217
+
218
+ // Ensure we actually have a conformance to Comparable for this element type.
219
+ auto comparable = getComparableDescriptor ();
220
+ auto conformance = conformsToProtocol (elt.Type , comparable);
221
+
222
+ // If we don't have a conformance then something somewhere messed up in
223
+ // deciding that this tuple type was Comparable...??
224
+ if (!conformance)
225
+ swift_unreachable (" Tuple comparability requires that all elements \
226
+ be Comparable." );
227
+
228
+ // Get the respective values from both tuples.
229
+ auto value1 = reinterpret_cast <OpaqueValue *>(
230
+ reinterpret_cast <char *>(tuple1) + elt.Offset );
231
+ auto value2 = reinterpret_cast <OpaqueValue *>(
232
+ reinterpret_cast <char *>(tuple2) + elt.Offset );
233
+
234
+ // First, grab the equatable conformance to prepare to check if the elements
235
+ // are equal. (Since this require Equatable conformance, the witness table
236
+ // is right after the conformance descriptor, which is at index 0.)
237
+ auto comparableTable = reinterpret_cast <void * const *>(conformance);
238
+ auto equatableTable = reinterpret_cast <void * const *>(comparableTable[1 ]);
239
+ auto equalsWitness = equatableTable[WitnessTableFirstRequirementOffset];
240
+ auto equals = reinterpret_cast <StaticInfixWitness *>(equalsWitness);
241
+
242
+ // Call the equal function.
243
+ auto isEqual = equals (value1, value2, elt.Type , elt.Type ,
244
+ reinterpret_cast <const WitnessTable *>(equatableTable));
245
+
246
+ // If these are equal, skip to the next element.
247
+ if (isEqual)
248
+ continue ;
249
+
250
+ // Now that we know they are not equal, we can call their less than function
251
+ // and return the result.
252
+ auto lessThanWitness = comparableTable[1 + WitnessTableFirstRequirementOffset];
253
+ auto lessThan = reinterpret_cast <StaticInfixWitness *>(lessThanWitness);
254
+
255
+ // Call the less than function.
256
+ auto isLessThan = lessThan (value1, value2, elt.Type , elt.Type , conformance);
257
+
258
+ return isLessThan;
259
+ }
260
+
261
+ // Otherwise these tuples are completely equal, thus they are not less than
262
+ // each other.
263
+ return false ;
264
+ }
265
+
266
+ SWIFT_RUNTIME_EXPORT SWIFT_CC (swift)
267
+ bool swift::_swift_tupleComparable_lessThanOrEqual(OpaqueValue *tuple1,
268
+ OpaqueValue *tuple2,
269
+ SWIFT_CONTEXT Metadata *swiftSelf,
270
+ Metadata *Self,
271
+ void *witnessTable) {
272
+ auto tuple = cast<TupleTypeMetadata>(Self);
273
+
274
+ // Loop through all elements, and check if both tuples element is equal.
275
+ for (size_t i = 0 ; i != tuple->NumElements ; i += 1 ) {
276
+ auto elt = tuple->getElement (i);
277
+
278
+ // Ensure we actually have a conformance to Comparable for this element type.
279
+ auto comparable = getComparableDescriptor ();
280
+ auto conformance = conformsToProtocol (elt.Type , comparable);
281
+
282
+ // If we don't have a conformance then something somewhere messed up in
283
+ // deciding that this tuple type was Comparable...??
284
+ if (!conformance)
285
+ swift_unreachable (" Tuple comparability requires that all elements \
286
+ be Comparable." );
287
+
288
+ // Get the respective values from both tuples.
289
+ auto value1 = reinterpret_cast <OpaqueValue *>(
290
+ reinterpret_cast <char *>(tuple1) + elt.Offset );
291
+ auto value2 = reinterpret_cast <OpaqueValue *>(
292
+ reinterpret_cast <char *>(tuple2) + elt.Offset );
293
+
294
+ // First, grab the equatable conformance to prepare to check if the elements
295
+ // are equal. (Since this require Equatable conformance, the witness table
296
+ // is right after the conformance descriptor, which is at index 0.)
297
+ auto comparableTable = reinterpret_cast <void * const *>(conformance);
298
+ auto equatableTable = reinterpret_cast <void * const *>(comparableTable[1 ]);
299
+ auto equalsWitness = equatableTable[WitnessTableFirstRequirementOffset];
300
+ auto equals = reinterpret_cast <StaticInfixWitness *>(equalsWitness);
301
+
302
+ // Call the equal function.
303
+ auto isEqual = equals (value1, value2, elt.Type , elt.Type ,
304
+ reinterpret_cast <const WitnessTable *>(equatableTable));
305
+
306
+ // If these are equal, skip to the next element.
307
+ if (isEqual)
308
+ continue ;
309
+
310
+ // Now that we know they are not equal, we can call their less than or equal
311
+ // function and return the result.
312
+ auto lessThanOrEqualWitness =
313
+ comparableTable[WitnessTableFirstRequirementOffset + 2 ];
314
+ auto lessThanOrEqual =
315
+ reinterpret_cast <StaticInfixWitness *>(lessThanOrEqualWitness);
316
+
317
+ // Call the less than function.
318
+ auto isLessThanOrEqual = lessThanOrEqual (value1, value2, elt.Type , elt.Type ,
319
+ conformance);
320
+
321
+ return isLessThanOrEqual;
322
+ }
323
+
324
+ // Otherwise these tuples are completely equal.
325
+ return true ;
326
+ }
327
+
328
+ SWIFT_RUNTIME_EXPORT SWIFT_CC (swift)
329
+ bool swift::_swift_tupleComparable_greaterThanOrEqual(OpaqueValue *tuple1,
330
+ OpaqueValue *tuple2,
331
+ SWIFT_CONTEXT Metadata *swiftSelf,
332
+ Metadata *Self,
333
+ void *witnessTable) {
334
+ auto tuple = cast<TupleTypeMetadata>(Self);
335
+
336
+ // Loop through all elements, and check if both tuples element is equal.
337
+ for (size_t i = 0 ; i != tuple->NumElements ; i += 1 ) {
338
+ auto elt = tuple->getElement (i);
339
+
340
+ // Ensure we actually have a conformance to Comparable for this element type.
341
+ auto comparable = getComparableDescriptor ();
342
+ auto conformance = conformsToProtocol (elt.Type , comparable);
343
+
344
+ // If we don't have a conformance then something somewhere messed up in
345
+ // deciding that this tuple type was Comparable...??
346
+ if (!conformance)
347
+ swift_unreachable (" Tuple comparability requires that all elements \
348
+ be Comparable." );
349
+
350
+ // Get the respective values from both tuples.
351
+ auto value1 = reinterpret_cast <OpaqueValue *>(
352
+ reinterpret_cast <char *>(tuple1) + elt.Offset );
353
+ auto value2 = reinterpret_cast <OpaqueValue *>(
354
+ reinterpret_cast <char *>(tuple2) + elt.Offset );
355
+
356
+ // First, grab the equatable conformance to prepare to check if the elements
357
+ // are equal. (Since this require Equatable conformance, the witness table
358
+ // is right after the conformance descriptor, which is at index 0.)
359
+ auto comparableTable = reinterpret_cast <void * const *>(conformance);
360
+ auto equatableTable = reinterpret_cast <void * const *>(comparableTable[1 ]);
361
+ auto equalsWitness = equatableTable[WitnessTableFirstRequirementOffset];
362
+ auto equals = reinterpret_cast <StaticInfixWitness *>(equalsWitness);
363
+
364
+ // Call the equal function.
365
+ auto isEqual = equals (value1, value2, elt.Type , elt.Type ,
366
+ reinterpret_cast <const WitnessTable *>(equatableTable));
367
+
368
+ // If these are equal, skip to the next element.
369
+ if (isEqual)
370
+ continue ;
371
+
372
+ // Now that we know they are not equal, we can call their greater than or
373
+ // equal function and return the result.
374
+ auto greaterThanOrEqualWitness =
375
+ comparableTable[WitnessTableFirstRequirementOffset + 3 ];
376
+ auto greaterThanOrEqual =
377
+ reinterpret_cast <StaticInfixWitness *>(greaterThanOrEqualWitness);
378
+
379
+ // Call the greater than or equal function.
380
+ auto isGreaterThanOrEqual = greaterThanOrEqual (value1, value2, elt.Type ,
381
+ elt.Type , conformance);
382
+
383
+ return isGreaterThanOrEqual;
384
+ }
385
+
386
+ // Otherwise these tuples are completely equal.
387
+ return true ;
388
+ }
389
+
390
+ SWIFT_RUNTIME_EXPORT SWIFT_CC (swift)
391
+ bool swift::_swift_tupleComparable_greaterThan(OpaqueValue *tuple1,
392
+ OpaqueValue *tuple2,
393
+ SWIFT_CONTEXT Metadata *swiftSelf,
394
+ Metadata *Self,
395
+ void *witnessTable) {
396
+ auto tuple = cast<TupleTypeMetadata>(Self);
397
+
398
+ // Loop through all elements, and check if both tuples element is equal.
399
+ for (size_t i = 0 ; i != tuple->NumElements ; i += 1 ) {
400
+ auto elt = tuple->getElement (i);
401
+
402
+ // Ensure we actually have a conformance to Comparable for this element type.
403
+ auto comparable = getComparableDescriptor ();
404
+ auto conformance = conformsToProtocol (elt.Type , comparable);
405
+
406
+ // If we don't have a conformance then something somewhere messed up in
407
+ // deciding that this tuple type was Comparable...??
408
+ if (!conformance)
409
+ swift_unreachable (" Tuple comparability requires that all elements \
410
+ be Comparable." );
411
+
412
+ // Get the respective values from both tuples.
413
+ auto value1 = reinterpret_cast <OpaqueValue *>(
414
+ reinterpret_cast <char *>(tuple1) + elt.Offset );
415
+ auto value2 = reinterpret_cast <OpaqueValue *>(
416
+ reinterpret_cast <char *>(tuple2) + elt.Offset );
417
+
418
+ // First, grab the equatable conformance to prepare to check if the elements
419
+ // are equal. (Since this require Equatable conformance, the witness table
420
+ // is right after the conformance descriptor, which is at index 0.)
421
+ auto comparableTable = reinterpret_cast <void * const *>(conformance);
422
+ auto equatableTable = reinterpret_cast <void * const *>(comparableTable[1 ]);
423
+ auto equalsWitness = equatableTable[WitnessTableFirstRequirementOffset];
424
+ auto equals = reinterpret_cast <StaticInfixWitness *>(equalsWitness);
425
+
426
+ // Call the equal function.
427
+ auto isEqual = equals (value1, value2, elt.Type , elt.Type ,
428
+ reinterpret_cast <const WitnessTable *>(equatableTable));
429
+
430
+ // If these are equal, skip to the next element.
431
+ if (isEqual)
432
+ continue ;
433
+
434
+ // Now that we know they are not equal, we can call their greater than
435
+ // function and return the result.
436
+ auto greaterThanWitness =
437
+ comparableTable[WitnessTableFirstRequirementOffset + 4 ];
438
+ auto greaterThan =
439
+ reinterpret_cast <StaticInfixWitness *>(greaterThanWitness);
440
+
441
+ // Call the greater than function.
442
+ auto isGreaterThan = greaterThan (value1, value2, elt.Type , elt.Type ,
443
+ conformance);
444
+
445
+ return isGreaterThan;
446
+ }
447
+
448
+ // Otherwise these tuples are completely equal, thus they are not greater than
449
+ // each other.
450
+ return false ;
451
+ }
0 commit comments