31
31
#include " swift/AST/CanTypeVisitor.h"
32
32
#include " swift/AST/Types.h"
33
33
#include " swift/AST/Decl.h"
34
+ #include " swift/AST/GenericEnvironment.h"
34
35
#include " swift/AST/IRGenOptions.h"
35
36
#include " swift/AST/SubstitutionMap.h"
36
37
#include " swift/ClangImporter/ClangModule.h"
74
75
using namespace swift ;
75
76
using namespace irgen ;
76
77
77
- // Return the offset one should do on a witness table pointer to retrieve the
78
- // `index`th piece of private data.
79
- static int privateIndexToTableOffset (unsigned index) { return -1 - (int )index; }
80
-
81
78
namespace {
82
79
83
80
// / A class for computing how to pass arguments to a polymorphic
@@ -574,30 +571,12 @@ void EmitPolymorphicParameters::bindExtraSource(const MetadataSource &source,
574
571
}
575
572
576
573
if (conformance.isConcrete ()) {
577
- // Now bind all the conditional witness tables that can be pulled out of
578
- // the self witness table.
579
- SILWitnessTable::enumerateWitnessTableConditionalConformances (
580
- conformance.getConcrete (),
581
- [&](unsigned index, CanType type, ProtocolDecl *proto) {
582
- auto archetype = getTypeInContext (type);
583
- if (isa<ArchetypeType>(archetype)) {
584
- WitnessIndex wIndex (privateIndexToTableOffset (index),
585
- /* prefix*/ false );
586
-
587
- auto table =
588
- emitInvariantLoadOfOpaqueWitness (IGF, selfTable, wIndex);
589
- table =
590
- IGF.Builder .CreateBitCast (table, IGF.IGM .WitnessTablePtrTy );
591
- setProtocolWitnessTableName (IGF.IGM , table, archetype, proto);
592
-
593
- IGF.setUnscopedLocalTypeData (
594
- archetype,
595
- LocalTypeDataKind::forAbstractProtocolWitnessTable (proto),
596
- table);
597
- }
598
-
599
- return /* finished?*/ false ;
600
- });
574
+ IGF.bindLocalTypeDataFromSelfWitnessTable (
575
+ conformance.getConcrete (),
576
+ selfTable,
577
+ [this ](CanType type) {
578
+ return getTypeInContext (type);
579
+ });
601
580
}
602
581
return ;
603
582
}
@@ -1017,7 +996,7 @@ class irgen::ConformanceInfo {
1017
996
};
1018
997
1019
998
static std::pair<llvm::Value *, llvm::Value *>
1020
- emitConditionalConformancesBuffer (IRGenFunction &IGF,
999
+ emitConditionalConformancesBuffer (IRGenFunction &IGF, CanType conformingType,
1021
1000
const ProtocolConformance *conformance) {
1022
1001
// Pointers to the witness tables, in the right order, which will be included
1023
1002
// in the buffer that gets passed to the witness table accessor.
@@ -1026,6 +1005,30 @@ emitConditionalConformancesBuffer(IRGenFunction &IGF,
1026
1005
auto subMap = conformance->getSubstitutions (IGF.IGM .getSwiftModule ());
1027
1006
auto rootConformance = conformance->getRootNormalConformance ();
1028
1007
1008
+ // Find the generic environment into which the witness table should be
1009
+ // mapped.
1010
+ // FIXME: Passing conformingType down for just this purpose feels like a
1011
+ // hack.
1012
+ if (conformingType->hasArchetype () &&
1013
+ conformance->getType ()->hasTypeParameter ()) {
1014
+ GenericEnvironment *conformingTypeEnv = nullptr ;
1015
+ conformingType.findIf ([&](Type type) {
1016
+ if (auto archetype = type->getAs <ArchetypeType>()) {
1017
+ conformingTypeEnv = archetype->getGenericEnvironment ();
1018
+ return conformingTypeEnv != nullptr ;
1019
+ }
1020
+
1021
+ return false ;
1022
+ });
1023
+
1024
+ if (conformingTypeEnv) {
1025
+ subMap = subMap.subst ([&](SubstitutableType *dependentType) {
1026
+ return conformingTypeEnv->mapTypeIntoContext (Type (dependentType));
1027
+ },
1028
+ LookUpConformanceInModule (IGF.getSwiftModule ()));
1029
+ }
1030
+ }
1031
+
1029
1032
SILWitnessTable::enumerateWitnessTableConditionalConformances (
1030
1033
rootConformance, [&](unsigned , CanType type, ProtocolDecl *proto) {
1031
1034
auto substType = type.subst (subMap)->getCanonicalType ();
@@ -1078,7 +1081,7 @@ static llvm::Value *emitWitnessTableAccessorCall(
1078
1081
1079
1082
llvm::Value *conditionalTables, *numConditionalTables;
1080
1083
std::tie (conditionalTables, numConditionalTables) =
1081
- emitConditionalConformancesBuffer (IGF, conformance);
1084
+ emitConditionalConformancesBuffer (IGF, conformingType, conformance);
1082
1085
1083
1086
call = IGF.Builder .CreateCall (
1084
1087
accessor, {*srcMetadataCache, conditionalTables, numConditionalTables});
@@ -1414,7 +1417,8 @@ class AccessorConformanceInfo : public ConformanceInfo {
1414
1417
unsigned index) {
1415
1418
assert (index < NextPrivateDataIndex);
1416
1419
return IGF.Builder .CreateConstArrayGEP (
1417
- table, privateIndexToTableOffset (index), IGF.IGM .getPointerSize ());
1420
+ table, privateWitnessTableIndexToTableOffset (index),
1421
+ IGF.IGM .getPointerSize ());
1418
1422
}
1419
1423
1420
1424
const FulfillmentMap &getFulfillmentMap () {
@@ -1488,6 +1492,13 @@ getAssociatedTypeMetadataAccessFunction(AssociatedType requirement,
1488
1492
Address destTable (parameters.claimNext (), IGM.getPointerAlignment ());
1489
1493
setProtocolWitnessTableName (IGM, destTable.getAddress (), ConcreteType,
1490
1494
requirement.getSourceProtocol ());
1495
+ IGF.bindLocalTypeDataFromSelfWitnessTable (
1496
+ &Conformance,
1497
+ destTable.getAddress (),
1498
+ [&](CanType type) {
1499
+ return Conformance.getDeclContext ()->mapTypeIntoContext (type)
1500
+ ->getCanonicalType ();
1501
+ });
1491
1502
1492
1503
// If the associated type is directly fulfillable from the type,
1493
1504
// we don't need a cache entry.
@@ -1541,7 +1552,7 @@ getOrCreateWitnessTableAccessFunction(IRGenModule &IGM, CanType type,
1541
1552
// function.
1542
1553
auto rootConformance = conformance->getRootNormalConformance ();
1543
1554
if (rootConformance->witnessTableAccessorRequiresArguments ()) {
1544
- return getWitnessTableLazyAccessFunction (IGM, rootConformance , type);
1555
+ return getWitnessTableLazyAccessFunction (IGM, conformance , type);
1545
1556
} else {
1546
1557
return IGM.getAddrOfWitnessTableAccessFunction (rootConformance,
1547
1558
NotForDefinition);
@@ -1601,6 +1612,13 @@ getAssociatedTypeWitnessTableAccessFunction(AssociatedConformance requirement,
1601
1612
Address destTable (parameters.claimNext (), IGM.getPointerAlignment ());
1602
1613
setProtocolWitnessTableName (IGM, destTable.getAddress (), ConcreteType,
1603
1614
Conformance.getProtocol ());
1615
+ IGF.bindLocalTypeDataFromSelfWitnessTable (
1616
+ &Conformance,
1617
+ destTable.getAddress (),
1618
+ [&](CanType type) {
1619
+ return Conformance.getDeclContext ()->mapTypeIntoContext (type)
1620
+ ->getCanonicalType ();
1621
+ });
1604
1622
1605
1623
ProtocolDecl *associatedProtocol = requirement.getAssociatedRequirement ();
1606
1624
@@ -1894,6 +1912,33 @@ llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
1894
1912
// All good: now we can actually fill in the witness table.
1895
1913
IGF.Builder .emitBlock (contBB);
1896
1914
1915
+ // / Run through the conditional conformance witness tables, pulling them out
1916
+ // / of the slice and putting them into the private data of the witness table.
1917
+ for (auto idx : indices (ConditionalRequirementPrivateDataIndices)) {
1918
+ Address conditionalTablePtr =
1919
+ IGF.Builder .CreateConstArrayGEP (conditionalTables, idx, PointerSize);
1920
+ Address slot = getAddressOfPrivateDataSlot (
1921
+ IGF, wtable, ConditionalRequirementPrivateDataIndices[idx]);
1922
+ auto conditionalTable = IGF.Builder .CreateLoad (conditionalTablePtr);
1923
+ auto coercedSlot =
1924
+ IGF.Builder .CreateElementBitCast (slot, conditionalTable->getType ());
1925
+ IGF.Builder .CreateStore (conditionalTable, coercedSlot);
1926
+
1927
+ // Register local type data for the conditional conformance witness table.
1928
+ const auto &condConformance = SILConditionalConformances[idx];
1929
+ CanType reqTypeInContext =
1930
+ Conformance.getDeclContext ()
1931
+ ->mapTypeIntoContext (condConformance.Requirement )
1932
+ ->getCanonicalType ();
1933
+ if (auto archetype = dyn_cast<ArchetypeType>(reqTypeInContext)) {
1934
+ auto condProto = condConformance.Conformance .getRequirement ();
1935
+ IGF.setUnscopedLocalTypeData (
1936
+ archetype,
1937
+ LocalTypeDataKind::forAbstractProtocolWitnessTable (condProto),
1938
+ conditionalTable);
1939
+ }
1940
+ }
1941
+
1897
1942
// Initialize all the specialized base conformances.
1898
1943
for (auto &base : SpecializedBaseConformances) {
1899
1944
// Ask the ConformanceInfo to emit the wtable.
@@ -1907,18 +1952,6 @@ llvm::Constant *WitnessTableBuilder::buildInstantiationFunction() {
1907
1952
IGF.Builder .CreateStore (baseWTable, slot);
1908
1953
}
1909
1954
1910
- // / Run through the conditional conformance witness tables, pulling them out
1911
- // / of the slice and putting them into the private data of the witness table.
1912
- for (auto idx : indices (ConditionalRequirementPrivateDataIndices)) {
1913
- Address conditionalTablePtr =
1914
- IGF.Builder .CreateConstArrayGEP (conditionalTables, idx, PointerSize);
1915
- Address slot = getAddressOfPrivateDataSlot (
1916
- IGF, wtable, ConditionalRequirementPrivateDataIndices[idx]);
1917
- auto conditionalTable = IGF.Builder .CreateLoad (conditionalTablePtr);
1918
- auto coercedSlot =
1919
- IGF.Builder .CreateElementBitCast (slot, conditionalTable->getType ());
1920
- IGF.Builder .CreateStore (conditionalTable, coercedSlot);
1921
- }
1922
1955
1923
1956
IGF.Builder .CreateRetVoid ();
1924
1957
@@ -2412,7 +2445,7 @@ llvm::Value *MetadataPath::followComponent(IRGenFunction &IGF,
2412
2445
LocalTypeDataKind::forAbstractProtocolWitnessTable (conformingProto);
2413
2446
2414
2447
if (source) {
2415
- WitnessIndex index (privateIndexToTableOffset (reqtIndex),
2448
+ WitnessIndex index (privateWitnessTableIndexToTableOffset (reqtIndex),
2416
2449
/* prefix*/ false );
2417
2450
2418
2451
source = emitInvariantLoadOfOpaqueWitness (IGF, source, index);
0 commit comments