@@ -334,6 +334,28 @@ void IRGenModule::emitNonoverriddenMethodDescriptor(const SILVTable *VTable,
334
334
getAddrOfLLVMVariable (entity, init, DebugTypeInfo ());
335
335
}
336
336
337
+ void IRGenModule::addVTableTypeMetadata (
338
+ ClassDecl *decl, llvm::GlobalVariable *var,
339
+ SmallVector<std::pair<Size, SILDeclRef>, 8 > vtableEntries) {
340
+ for (auto ventry : vtableEntries) {
341
+ auto method = ventry.second ;
342
+ auto offset = ventry.first .getValue ();
343
+ var->addTypeMetadata (offset, typeIdForMethod (*this , method));
344
+ }
345
+
346
+ auto AS = decl->getFormalAccessScope ();
347
+ if (AS.isFileScope ()) {
348
+ var->setVCallVisibilityMetadata (
349
+ llvm::GlobalObject::VCallVisibility::VCallVisibilityTranslationUnit);
350
+ } else if (AS.isPrivate () || AS.isInternal ()) {
351
+ var->setVCallVisibilityMetadata (
352
+ llvm::GlobalObject::VCallVisibility::VCallVisibilityLinkageUnit);
353
+ } else {
354
+ var->setVCallVisibilityMetadata (
355
+ llvm::GlobalObject::VCallVisibility::VCallVisibilityPublic);
356
+ }
357
+ }
358
+
337
359
namespace {
338
360
template <class Impl >
339
361
class ContextDescriptorBuilderBase {
@@ -1232,7 +1254,11 @@ namespace {
1232
1254
auto addr = IGM.getAddrOfTypeContextDescriptor (Type, HasMetadata,
1233
1255
B.finishAndCreateFuture ());
1234
1256
auto var = cast<llvm::GlobalVariable>(addr);
1235
-
1257
+
1258
+ if (IGM.getOptions ().VirtualFunctionElimination ) {
1259
+ asImpl ().addVTableTypeMetadata (var);
1260
+ }
1261
+
1236
1262
var->setConstant (true );
1237
1263
IGM.setTrueConstGlobal (var);
1238
1264
return var;
@@ -1440,6 +1466,10 @@ namespace {
1440
1466
B.addRelativeAddress (IGM.getAddrOfReflectionFieldDescriptor (
1441
1467
getType ()->getDeclaredType ()->getCanonicalType ()));
1442
1468
}
1469
+
1470
+ void addVTableTypeMetadata (llvm::GlobalVariable *var) {
1471
+ // Structs don't have vtables.
1472
+ }
1443
1473
};
1444
1474
1445
1475
class EnumContextDescriptorBuilder
@@ -1522,6 +1552,10 @@ namespace {
1522
1552
B.addRelativeAddress (IGM.getAddrOfReflectionFieldDescriptor (
1523
1553
getType ()->getDeclaredType ()->getCanonicalType ()));
1524
1554
}
1555
+
1556
+ void addVTableTypeMetadata (llvm::GlobalVariable *var) {
1557
+ // Enums don't have vtables.
1558
+ }
1525
1559
};
1526
1560
1527
1561
class ClassContextDescriptorBuilder
@@ -1547,6 +1581,11 @@ namespace {
1547
1581
SmallVector<SILDeclRef, 8 > VTableEntries;
1548
1582
SmallVector<std::pair<SILDeclRef, SILDeclRef>, 8 > OverrideTableEntries;
1549
1583
1584
+ // As we're constructing the vtable, VTableEntriesForVFE stores the offset
1585
+ // (from the beginning of the global) for each vtable slot. The offsets are
1586
+ // later turned into !type metadata attributes.
1587
+ SmallVector<std::pair<Size, SILDeclRef>, 8 > VTableEntriesForVFE;
1588
+
1550
1589
public:
1551
1590
ClassContextDescriptorBuilder (IRGenModule &IGM, ClassDecl *Type,
1552
1591
RequireMetadata_t requireMetadata)
@@ -1703,6 +1742,13 @@ namespace {
1703
1742
IGM.defineMethodDescriptor (fn, Type,
1704
1743
B.getAddrOfCurrentPosition (IGM.MethodDescriptorStructTy ));
1705
1744
1745
+ if (IGM.getOptions ().VirtualFunctionElimination ) {
1746
+ auto offset = B.getNextOffsetFromGlobal () +
1747
+ // 1st field of MethodDescriptorStructTy
1748
+ Size (IGM.DataLayout .getTypeAllocSize (IGM.Int32Ty ));
1749
+ VTableEntriesForVFE.push_back (std::pair<Size, SILDeclRef>(offset, fn));
1750
+ }
1751
+
1706
1752
// Actually build the descriptor.
1707
1753
auto descriptor = B.beginStruct (IGM.MethodDescriptorStructTy );
1708
1754
buildMethodDescriptorFields (IGM, VTable, fn, descriptor);
@@ -1715,7 +1761,15 @@ namespace {
1715
1761
IGM.emitDispatchThunk (fn);
1716
1762
}
1717
1763
}
1718
-
1764
+
1765
+ void addVTableTypeMetadata (llvm::GlobalVariable *var) {
1766
+ if (!IGM.getOptions ().VirtualFunctionElimination )
1767
+ return ;
1768
+ assert (VTable && " no vtable?!" );
1769
+
1770
+ IGM.addVTableTypeMetadata (getType (), var, VTableEntriesForVFE);
1771
+ }
1772
+
1719
1773
void emitNonoverriddenMethod (SILDeclRef fn) {
1720
1774
// TODO: Derivative functions do not distinguish themselves in the mangled
1721
1775
// names of method descriptor symbols yet, causing symbol name collisions.
@@ -1731,7 +1785,14 @@ namespace {
1731
1785
if (hasPublicVisibility (fn.getLinkage (NotForDefinition))) {
1732
1786
IGM.emitDispatchThunk (fn);
1733
1787
}
1734
-
1788
+
1789
+ if (IGM.getOptions ().VirtualFunctionElimination ) {
1790
+ auto offset = B.getNextOffsetFromGlobal () +
1791
+ // 1st field of MethodDescriptorStructTy
1792
+ Size (IGM.DataLayout .getTypeAllocSize (IGM.Int32Ty ));
1793
+ VTableEntriesForVFE.push_back (std::pair<Size, SILDeclRef>(offset, fn));
1794
+ }
1795
+
1735
1796
// Emit a freestanding method descriptor structure. This doesn't have to
1736
1797
// exist in the table in the class's context descriptor since it isn't
1737
1798
// in the vtable, but external clients need to be able to link against the
@@ -1761,6 +1822,17 @@ namespace {
1761
1822
}
1762
1823
1763
1824
void emitMethodOverrideDescriptor (SILDeclRef baseRef, SILDeclRef declRef) {
1825
+ if (IGM.getOptions ().VirtualFunctionElimination ) {
1826
+ auto offset =
1827
+ B.getNextOffsetFromGlobal () +
1828
+ // 1st field of MethodOverrideDescriptorStructTy
1829
+ Size (IGM.DataLayout .getTypeAllocSize (IGM.RelativeAddressTy )) +
1830
+ // 2nd field of MethodOverrideDescriptorStructTy
1831
+ Size (IGM.DataLayout .getTypeAllocSize (IGM.RelativeAddressTy ));
1832
+ VTableEntriesForVFE.push_back (
1833
+ std::pair<Size, SILDeclRef>(offset, baseRef));
1834
+ }
1835
+
1764
1836
auto descriptor = B.beginStruct (IGM.MethodOverrideDescriptorStructTy );
1765
1837
1766
1838
// The class containing the base method.
@@ -2900,6 +2972,11 @@ namespace {
2900
2972
2901
2973
Size AddressPoint;
2902
2974
2975
+ // As we're constructing the vtable, VTableEntriesForVFE stores the offset
2976
+ // (from the beginning of the global) for each vtable slot. The offsets are
2977
+ // later turned into !type metadata attributes.
2978
+ SmallVector<std::pair<Size, SILDeclRef>, 8 > VTableEntriesForVFE;
2979
+
2903
2980
public:
2904
2981
ClassMetadataBuilderBase (IRGenModule &IGM, ClassDecl *theClass,
2905
2982
ConstantStructBuilder &builder,
@@ -3201,12 +3278,21 @@ namespace {
3201
3278
}
3202
3279
}
3203
3280
3281
+ if (IGM.getOptions ().VirtualFunctionElimination ) {
3282
+ auto offset = B.getNextOffsetFromGlobal ();
3283
+ VTableEntriesForVFE.push_back (std::pair<Size, SILDeclRef>(offset, fn));
3284
+ }
3285
+
3204
3286
PointerAuthSchema schema =
3205
3287
afd->hasAsync () ? IGM.getOptions ().PointerAuth .AsyncSwiftClassMethods
3206
3288
: IGM.getOptions ().PointerAuth .SwiftClassMethods ;
3207
3289
B.addSignedPointer (ptr, schema, fn);
3208
3290
}
3209
3291
3292
+ SmallVector<std::pair<Size, SILDeclRef>, 8 > getVTableEntriesForVFE () {
3293
+ return VTableEntriesForVFE;
3294
+ }
3295
+
3210
3296
void addPlaceholder (MissingMemberDecl *m) {
3211
3297
assert (m->getNumberOfVTableEntries () == 0
3212
3298
&& " cannot generate metadata with placeholders in it" );
@@ -3805,6 +3891,7 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
3805
3891
bool canBeConstant;
3806
3892
3807
3893
auto strategy = IGM.getClassMetadataStrategy (classDecl);
3894
+ SmallVector<std::pair<Size, SILDeclRef>, 8 > vtableEntries;
3808
3895
3809
3896
switch (strategy) {
3810
3897
case ClassMetadataStrategy::Resilient: {
@@ -3846,6 +3933,9 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
3846
3933
canBeConstant = builder.canBeConstant ();
3847
3934
3848
3935
builder.createMetadataAccessFunction ();
3936
+ if (IGM.getOptions ().VirtualFunctionElimination ) {
3937
+ vtableEntries = builder.getVTableEntriesForVFE ();
3938
+ }
3849
3939
break ;
3850
3940
}
3851
3941
}
@@ -3859,7 +3949,8 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
3859
3949
3860
3950
bool isPattern = (strategy == ClassMetadataStrategy::Resilient);
3861
3951
auto var = IGM.defineTypeMetadata (declaredType, isPattern, canBeConstant,
3862
- init.finishAndCreateFuture (), section);
3952
+ init.finishAndCreateFuture (), section,
3953
+ vtableEntries);
3863
3954
3864
3955
// If the class does not require dynamic initialization, or if it only
3865
3956
// requires dynamic initialization on a newer Objective-C runtime, add it
0 commit comments