forked from swiftlang/swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathLinking.h
663 lines (552 loc) · 21.8 KB
/
Linking.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
//===--- Linking.h - Common declarations for link information ---*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines structures and routines used when creating global
// entities that are placed in the LLVM module, potentially with
// external linkage.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_LINKING_H
#define SWIFT_IRGEN_LINKING_H
#include "swift/AST/Types.h"
#include "swift/AST/Decl.h"
#include "swift/SIL/SILModule.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/GlobalValue.h"
#include "DebugTypeInfo.h"
#include "IRGen.h"
#include "IRGenModule.h"
#include "ValueWitness.h"
namespace llvm {
class AttributeSet;
class Value;
class FunctionType;
}
namespace swift {
namespace irgen {
class TypeInfo;
class IRGenModule;
/// Selector for type metadata symbol kinds.
enum class TypeMetadataAddress {
AddressPoint,
FullMetadata,
};
/// A link entity is some sort of named declaration, combined with all
/// the information necessary to distinguish specific implementations
/// of the declaration from each other.
///
/// For example, functions may be uncurried at different levels, each of
/// which potentially creates a different top-level function.
class LinkEntity {
/// ValueDecl*, SILFunction*, or TypeBase*, depending on Kind.
void *Pointer;
/// ProtocolConformance*, depending on Kind.
void *SecondaryPointer;
/// A hand-rolled bitfield with the following layout:
unsigned Data;
enum : unsigned {
KindShift = 0, KindMask = 0xFF,
// These fields appear in decl kinds.
UncurryLevelShift = 8, UncurryLevelMask = 0xFF00,
// This field appears in the ValueWitness kind.
ValueWitnessShift = 8, ValueWitnessMask = 0xFF00,
// These fields appear in the FieldOffset kind.
IsIndirectShift = 8, IsIndirectMask = 0x0100,
// These fields appear in the TypeMetadata kind.
MetadataAddressShift = 8, MetadataAddressMask = 0x0300,
IsPatternShift = 10, IsPatternMask = 0x0400,
// This field appears in associated type access function kinds.
AssociatedTypeIndexShift = 8, AssociatedTypeIndexMask = ~KindMask,
};
#define LINKENTITY_SET_FIELD(field, value) (value << field##Shift)
#define LINKENTITY_GET_FIELD(value, field) ((value & field##Mask) >> field##Shift)
enum class Kind {
/// A function.
/// The pointer is a FuncDecl*.
Function,
/// The offset to apply to a witness table or metadata object
/// in order to find the information for a declaration. The
/// pointer is a ValueDecl*.
WitnessTableOffset,
/// A field offset. The pointer is a VarDecl*.
FieldOffset,
/// An Objective-C class reference. The pointer is a ClassDecl*.
ObjCClass,
/// An Objective-C class reference reference. The pointer is a ClassDecl*.
ObjCClassRef,
/// An Objective-C metaclass reference. The pointer is a ClassDecl*.
ObjCMetaclass,
/// A swift metaclass-stub reference. The pointer is a ClassDecl*.
SwiftMetaclassStub,
/// The nominal type descriptor for a nominal type.
/// The pointer is a NominalTypeDecl*.
NominalTypeDescriptor,
/// The protocol descriptor for a protocol type.
/// The pointer is a ProtocolDecl*.
ProtocolDescriptor,
/// Some other kind of declaration.
/// The pointer is a Decl*.
Other,
/// A SIL function. The pointer is a SILFunction*.
SILFunction,
/// A SIL global variable. The pointer is a SILGlobalVariable*.
SILGlobalVariable,
// These next few are protocol-conformance kinds.
/// A direct protocol witness table. The secondary pointer is a
/// ProtocolConformance*.
DirectProtocolWitnessTable,
/// A witness accessor function. The secondary pointer is a
/// ProtocolConformance*.
ProtocolWitnessTableAccessFunction,
/// A generic protocol witness table cache. The secondary pointer is a
/// ProtocolConformance*.
GenericProtocolWitnessTableCache,
/// The instantiation function for a generic protocol witness table.
/// The secondary pointer is a ProtocolConformance*.
GenericProtocolWitnessTableInstantiationFunction,
/// A function which returns the type metadata for the associated type
/// of a protocol. The secondary pointer is a ProtocolConformance*.
/// The index of the associated type declaration is stored in the data.
AssociatedTypeMetadataAccessFunction,
/// A function which returns the witness table for a protocol-constrained
/// associated type of a protocol. The secondary pointer is a
/// ProtocolConformance*. The primary pointer is a ProtocolDecl*.
/// The index of the associated type declaration is stored in the data.
AssociatedTypeWitnessTableAccessFunction,
// These are both type kinds and protocol-conformance kinds.
/// A lazy protocol witness accessor function. The pointer is a
/// canonical TypeBase*, and the secondary pointer is a
/// ProtocolConformance*.
ProtocolWitnessTableLazyAccessFunction,
/// A lazy protocol witness cache variable. The pointer is a
/// canonical TypeBase*, and the secondary pointer is a
/// ProtocolConformance*.
ProtocolWitnessTableLazyCacheVariable,
// Everything following this is a type kind.
/// A value witness for a type.
/// The pointer is a canonical TypeBase*.
ValueWitness,
/// The value witness table for a type.
/// The pointer is a canonical TypeBase*.
ValueWitnessTable,
/// The metadata or metadata template for a type.
/// The pointer is a canonical TypeBase*.
TypeMetadata,
/// An access function for type metadata.
/// The pointer is a canonical TypeBase*.
TypeMetadataAccessFunction,
/// A lazy cache variable for type metadata.
/// The pointer is a canonical TypeBase*.
TypeMetadataLazyCacheVariable,
/// A foreign type metadata candidate.
/// The pointer is a canonical TypeBase*.
ForeignTypeMetadataCandidate,
/// A type which is being mangled just for its string.
/// The pointer is a canonical TypeBase*.
TypeMangling,
};
friend struct llvm::DenseMapInfo<LinkEntity>;
static bool isFunction(ValueDecl *decl) {
return (isa<FuncDecl>(decl) || isa<EnumElementDecl>(decl) ||
isa<ConstructorDecl>(decl));
}
static bool hasGetterSetter(ValueDecl *decl) {
return (isa<VarDecl>(decl) || isa<SubscriptDecl>(decl));
}
Kind getKind() const {
return Kind(LINKENTITY_GET_FIELD(Data, Kind));
}
static bool isDeclKind(Kind k) {
return k <= Kind::Other;
}
static bool isTypeKind(Kind k) {
return k >= Kind::ProtocolWitnessTableLazyAccessFunction;
}
static bool isProtocolConformanceKind(Kind k) {
return k >= Kind::DirectProtocolWitnessTable
&& k <= Kind::ProtocolWitnessTableLazyCacheVariable;
}
void setForDecl(Kind kind, ValueDecl *decl, unsigned uncurryLevel) {
assert(isDeclKind(kind));
Pointer = decl;
SecondaryPointer = nullptr;
Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind))
| LINKENTITY_SET_FIELD(UncurryLevel, uncurryLevel);
}
void setForProtocolConformance(Kind kind, const ProtocolConformance *c) {
assert(isProtocolConformanceKind(kind) && !isTypeKind(kind));
Pointer = nullptr;
SecondaryPointer = const_cast<void*>(static_cast<const void*>(c));
Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind));
}
void setForProtocolConformanceAndType(Kind kind, const ProtocolConformance *c,
CanType type) {
assert(isProtocolConformanceKind(kind) && isTypeKind(kind));
Pointer = type.getPointer();
SecondaryPointer = const_cast<void*>(static_cast<const void*>(c));
Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind));
}
void setForProtocolConformanceAndAssociatedType(Kind kind,
const ProtocolConformance *c,
AssociatedTypeDecl *associate,
ProtocolDecl *associatedProtocol = nullptr) {
assert(isProtocolConformanceKind(kind));
Pointer = associatedProtocol;
SecondaryPointer = const_cast<void*>(static_cast<const void*>(c));
Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind)) |
LINKENTITY_SET_FIELD(AssociatedTypeIndex,
getAssociatedTypeIndex(c, associate));
}
// We store associated types using their index in their parent protocol
// in order to avoid bloating LinkEntity out to three key pointers.
static unsigned getAssociatedTypeIndex(const ProtocolConformance *conformance,
AssociatedTypeDecl *associate) {
assert(conformance->getProtocol() == associate->getProtocol());
unsigned result = 0;
for (auto requirement : associate->getProtocol()->getMembers()) {
if (requirement == associate) return result;
if (isa<AssociatedTypeDecl>(requirement)) result++;
}
llvm_unreachable("didn't find associated type in protocol?");
}
static AssociatedTypeDecl *
getAssociatedTypeByIndex(const ProtocolConformance *conformance,
unsigned index) {
for (auto requirement : conformance->getProtocol()->getMembers()) {
if (auto associate = dyn_cast<AssociatedTypeDecl>(requirement)) {
if (index == 0) return associate;
index--;
}
}
llvm_unreachable("didn't find associated type in protocol?");
}
void setForType(Kind kind, CanType type) {
assert(isTypeKind(kind));
Pointer = type.getPointer();
SecondaryPointer = nullptr;
Data = LINKENTITY_SET_FIELD(Kind, unsigned(kind));
}
LinkEntity() = default;
public:
static LinkEntity forNonFunction(ValueDecl *decl) {
assert(!isFunction(decl));
LinkEntity entity;
entity.setForDecl(Kind::Other, decl, 0);
return entity;
}
static LinkEntity forWitnessTableOffset(ValueDecl *decl,
unsigned uncurryLevel) {
LinkEntity entity;
entity.setForDecl(Kind::WitnessTableOffset, decl, uncurryLevel);
return entity;
}
static LinkEntity forFieldOffset(VarDecl *decl, bool isIndirect) {
LinkEntity entity;
entity.Pointer = decl;
entity.SecondaryPointer = nullptr;
entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::FieldOffset))
| LINKENTITY_SET_FIELD(IsIndirect, unsigned(isIndirect));
return entity;
}
static LinkEntity forObjCClassRef(ClassDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::ObjCClassRef, decl, 0);
return entity;
}
static LinkEntity forObjCClass(ClassDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::ObjCClass, decl, 0);
return entity;
}
static LinkEntity forObjCMetaclass(ClassDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::ObjCMetaclass, decl, 0);
return entity;
}
static LinkEntity forSwiftMetaclassStub(ClassDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::SwiftMetaclassStub, decl, 0);
return entity;
}
static LinkEntity forTypeMetadata(CanType concreteType,
TypeMetadataAddress addr,
bool isPattern) {
LinkEntity entity;
entity.Pointer = concreteType.getPointer();
entity.SecondaryPointer = nullptr;
entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::TypeMetadata))
| LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr))
| LINKENTITY_SET_FIELD(IsPattern, unsigned(isPattern));
return entity;
}
static LinkEntity forTypeMetadataAccessFunction(CanType type) {
LinkEntity entity;
entity.setForType(Kind::TypeMetadataAccessFunction, type);
return entity;
}
static LinkEntity forTypeMetadataLazyCacheVariable(CanType type) {
LinkEntity entity;
entity.setForType(Kind::TypeMetadataLazyCacheVariable, type);
return entity;
}
static LinkEntity forForeignTypeMetadataCandidate(CanType type) {
LinkEntity entity;
entity.setForType(Kind::ForeignTypeMetadataCandidate, type);
return entity;
}
static LinkEntity forNominalTypeDescriptor(NominalTypeDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::NominalTypeDescriptor, decl, 0);
return entity;
}
static LinkEntity forProtocolDescriptor(ProtocolDecl *decl) {
LinkEntity entity;
entity.setForDecl(Kind::ProtocolDescriptor, decl, 0);
return entity;
}
static LinkEntity forValueWitness(CanType concreteType, ValueWitness witness) {
LinkEntity entity;
entity.Pointer = concreteType.getPointer();
entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::ValueWitness))
| LINKENTITY_SET_FIELD(ValueWitness, unsigned(witness));
return entity;
}
static LinkEntity forValueWitnessTable(CanType type) {
LinkEntity entity;
entity.setForType(Kind::ValueWitnessTable, type);
return entity;
}
static LinkEntity forTypeMangling(CanType type) {
LinkEntity entity;
entity.setForType(Kind::TypeMangling, type);
return entity;
}
static LinkEntity forSILFunction(SILFunction *F)
{
LinkEntity entity;
entity.Pointer = F;
entity.SecondaryPointer = nullptr;
entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::SILFunction));
return entity;
}
static LinkEntity forSILGlobalVariable(SILGlobalVariable *G) {
LinkEntity entity;
entity.Pointer = G;
entity.SecondaryPointer = nullptr;
entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::SILGlobalVariable));
return entity;
}
static LinkEntity
forDirectProtocolWitnessTable(const ProtocolConformance *C) {
LinkEntity entity;
entity.setForProtocolConformance(Kind::DirectProtocolWitnessTable, C);
return entity;
}
static LinkEntity
forProtocolWitnessTableAccessFunction(const ProtocolConformance *C) {
LinkEntity entity;
entity.setForProtocolConformance(Kind::ProtocolWitnessTableAccessFunction,
C);
return entity;
}
static LinkEntity
forGenericProtocolWitnessTableCache(const ProtocolConformance *C) {
LinkEntity entity;
entity.setForProtocolConformance(Kind::GenericProtocolWitnessTableCache, C);
return entity;
}
static LinkEntity
forGenericProtocolWitnessTableInstantiationFunction(
const ProtocolConformance *C) {
LinkEntity entity;
entity.setForProtocolConformance(
Kind::GenericProtocolWitnessTableInstantiationFunction, C);
return entity;
}
static LinkEntity
forProtocolWitnessTableLazyAccessFunction(const ProtocolConformance *C,
CanType type) {
LinkEntity entity;
entity.setForProtocolConformanceAndType(
Kind::ProtocolWitnessTableLazyAccessFunction, C, type);
return entity;
}
static LinkEntity
forProtocolWitnessTableLazyCacheVariable(const ProtocolConformance *C,
CanType type) {
LinkEntity entity;
entity.setForProtocolConformanceAndType(
Kind::ProtocolWitnessTableLazyCacheVariable, C, type);
return entity;
}
static LinkEntity
forAssociatedTypeMetadataAccessFunction(const ProtocolConformance *C,
AssociatedTypeDecl *associate) {
LinkEntity entity;
entity.setForProtocolConformanceAndAssociatedType(
Kind::AssociatedTypeMetadataAccessFunction, C, associate);
return entity;
}
static LinkEntity
forAssociatedTypeWitnessTableAccessFunction(const ProtocolConformance *C,
AssociatedTypeDecl *associate,
ProtocolDecl *associateProtocol) {
LinkEntity entity;
entity.setForProtocolConformanceAndAssociatedType(
Kind::AssociatedTypeWitnessTableAccessFunction, C, associate,
associateProtocol);
return entity;
}
void mangle(llvm::raw_ostream &out) const;
void mangle(SmallVectorImpl<char> &buffer) const;
SILLinkage getLinkage(IRGenModule &IGM, ForDefinition_t isDefinition) const;
/// Returns true if this function or global variable is potentially defined
/// in a different module.
///
bool isAvailableExternally(IRGenModule &IGM) const;
ValueDecl *getDecl() const {
assert(isDeclKind(getKind()));
return reinterpret_cast<ValueDecl*>(Pointer);
}
SILFunction *getSILFunction() const {
assert(getKind() == Kind::SILFunction);
return reinterpret_cast<SILFunction*>(Pointer);
}
SILGlobalVariable *getSILGlobalVariable() const {
assert(getKind() == Kind::SILGlobalVariable);
return reinterpret_cast<SILGlobalVariable*>(Pointer);
}
const ProtocolConformance *getProtocolConformance() const {
assert(isProtocolConformanceKind(getKind()));
return reinterpret_cast<ProtocolConformance*>(SecondaryPointer);
}
AssociatedTypeDecl *getAssociatedType() const {
assert(getKind() == Kind::AssociatedTypeMetadataAccessFunction ||
getKind() == Kind::AssociatedTypeWitnessTableAccessFunction);
return getAssociatedTypeByIndex(getProtocolConformance(),
LINKENTITY_GET_FIELD(Data, AssociatedTypeIndex));
}
ProtocolDecl *getAssociatedProtocol() const {
assert(getKind() == Kind::AssociatedTypeWitnessTableAccessFunction);
return reinterpret_cast<ProtocolDecl*>(Pointer);
}
unsigned getUncurryLevel() const {
return LINKENTITY_GET_FIELD(Data, UncurryLevel);
}
bool isValueWitness() const { return getKind() == Kind::ValueWitness; }
CanType getType() const {
assert(isTypeKind(getKind()));
return CanType(reinterpret_cast<TypeBase*>(Pointer));
}
ValueWitness getValueWitness() const {
assert(getKind() == Kind::ValueWitness);
return ValueWitness(LINKENTITY_GET_FIELD(Data, ValueWitness));
}
TypeMetadataAddress getMetadataAddress() const {
assert(getKind() == Kind::TypeMetadata);
return (TypeMetadataAddress)LINKENTITY_GET_FIELD(Data, MetadataAddress);
}
bool isMetadataPattern() const {
assert(getKind() == Kind::TypeMetadata);
return LINKENTITY_GET_FIELD(Data, IsPattern);
}
bool isForeignTypeMetadataCandidate() const {
return getKind() == Kind::ForeignTypeMetadataCandidate;
}
bool isOffsetIndirect() const {
assert(getKind() == Kind::FieldOffset);
return LINKENTITY_GET_FIELD(Data, IsIndirect);
}
/// Determine whether this entity will be weak-imported.
bool isWeakImported(Module *module) const {
if (getKind() == Kind::SILGlobalVariable &&
getSILGlobalVariable()->getDecl())
return getSILGlobalVariable()->getDecl()->isWeakImported(module);
if (!isDeclKind(getKind()))
return false;
return getDecl()->isWeakImported(module);
}
#undef LINKENTITY_GET_FIELD
#undef LINKENTITY_SET_FIELD
};
/// Encapsulated information about the linkage of an entity.
class LinkInfo {
LinkInfo() = default;
llvm::SmallString<32> Name;
llvm::GlobalValue::LinkageTypes Linkage;
llvm::GlobalValue::VisibilityTypes Visibility;
ForDefinition_t ForDefinition;
public:
/// Compute linkage information for the given
static LinkInfo get(IRGenModule &IGM, const LinkEntity &entity,
ForDefinition_t forDefinition);
StringRef getName() const {
return Name.str();
}
llvm::GlobalValue::LinkageTypes getLinkage() const {
return Linkage;
}
llvm::GlobalValue::VisibilityTypes getVisibility() const {
return Visibility;
}
llvm::Function *createFunction(IRGenModule &IGM,
llvm::FunctionType *fnType,
llvm::CallingConv::ID cc,
const llvm::AttributeSet &attrs,
llvm::Function *insertBefore = nullptr);
llvm::GlobalVariable *createVariable(IRGenModule &IGM,
llvm::Type *objectType,
Alignment alignment,
DebugTypeInfo DebugType=DebugTypeInfo(),
Optional<SILLocation> DebugLoc = None,
StringRef DebugName = StringRef());
bool isUsed() const {
return ForDefinition && isUsed(Linkage, Visibility);
}
static bool isUsed(llvm::GlobalValue::LinkageTypes Linkage,
llvm::GlobalValue::VisibilityTypes Visibility);
};
} // end namespace irgen
} // end namespace swift
/// Allow LinkEntity to be used as a key for a DenseMap.
template <> struct llvm::DenseMapInfo<swift::irgen::LinkEntity> {
typedef swift::irgen::LinkEntity LinkEntity;
static LinkEntity getEmptyKey() {
LinkEntity entity;
entity.Pointer = nullptr;
entity.SecondaryPointer = nullptr;
entity.Data = 0;
return entity;
}
static LinkEntity getTombstoneKey() {
LinkEntity entity;
entity.Pointer = nullptr;
entity.SecondaryPointer = nullptr;
entity.Data = 1;
return entity;
}
static unsigned getHashValue(const LinkEntity &entity) {
return DenseMapInfo<void*>::getHashValue(entity.Pointer)
^ DenseMapInfo<void*>::getHashValue(entity.SecondaryPointer)
^ entity.Data;
}
static bool isEqual(const LinkEntity &LHS, const LinkEntity &RHS) {
return LHS.Pointer == RHS.Pointer &&
LHS.SecondaryPointer == RHS.SecondaryPointer &&
LHS.Data == RHS.Data;
}
};
#endif