19
19
#include " ConstantBuilder.h"
20
20
#include " Explosion.h"
21
21
#include " FixedTypeInfo.h"
22
- #include " GenericRequirement.h"
23
22
#include " GenArchetype.h"
24
23
#include " GenClass.h"
25
24
#include " GenMeta.h"
26
25
#include " GenProto.h"
27
26
#include " GenType.h"
27
+ #include " GenericRequirement.h"
28
28
#include " IRGenDebugInfo.h"
29
29
#include " IRGenFunction.h"
30
30
#include " IRGenMangler.h"
31
31
#include " IRGenModule.h"
32
32
#include " swift/AST/ASTContext.h"
33
33
#include " swift/AST/ExistentialLayout.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"
37
38
#include " swift/IRGen/Linking.h"
38
39
#include " swift/SIL/FormalLinkage.h"
39
40
#include " swift/SIL/TypeLowering.h"
41
+ #include " llvm/ADT/STLExtras.h"
42
+ #include " llvm/IR/Constant.h"
43
+ #include " llvm/Support/FormatVariadic.h"
44
+ #include < algorithm>
40
45
41
46
using namespace swift ;
42
47
using namespace irgen ;
@@ -1765,6 +1770,74 @@ IRGenFunction::emitGenericTypeMetadataAccessFunctionCall(
1765
1770
return MetadataResponse::handle (*this , request, call);
1766
1771
}
1767
1772
1773
+ static void emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction (
1774
+ IRGenFunction &IGF, Explosion ¶ms, NominalTypeDecl *nominal,
1775
+ GenericArguments &genericArgs,
1776
+ std::function<llvm::Value *(int )> valueAtIndex) {
1777
+ auto &IGM = IGF.IGM ;
1778
+ auto specializations = IGF.IGM .IRGen .specializationsForType (nominal);
1779
+ if (specializations.size () > 0 ) {
1780
+ SmallVector<llvm::BasicBlock *, 4 > conditionBlocks;
1781
+ for (size_t index = 0 ; index < specializations.size (); ++index) {
1782
+ conditionBlocks.push_back (llvm::BasicBlock::Create (IGM.getLLVMContext ()));
1783
+ }
1784
+
1785
+ IGF.Builder .CreateBr (conditionBlocks[0 ]);
1786
+
1787
+ SmallVector<std::pair<llvm::BasicBlock *, llvm::Value *>, 4 >
1788
+ specializationBlocks;
1789
+ auto switchDestination = llvm::BasicBlock::Create (IGM.getLLVMContext ());
1790
+ unsigned long index = 0 ;
1791
+ for (auto specialization : specializations) {
1792
+ auto conditionBlock = conditionBlocks[index];
1793
+ IGF.Builder .emitBlock (conditionBlock);
1794
+ auto successorBlock = index < conditionBlocks.size () - 1
1795
+ ? conditionBlocks[index + 1 ]
1796
+ : switchDestination;
1797
+ auto specializationBlock = llvm::BasicBlock::Create (IGM.getLLVMContext ());
1798
+ auto substitutions = specialization->getContextSubstitutionMap (
1799
+ IGM.getSwiftModule (), nominal);
1800
+
1801
+ llvm::Value *condition = llvm::ConstantInt::get (IGM.Int1Ty , 1 );
1802
+ auto generic = specialization->getAnyGeneric ();
1803
+ auto parameters = generic->getGenericEnvironment ()->getGenericParams ();
1804
+ for (size_t index = 0 ; index < parameters.size (); ++index) {
1805
+ auto parameter = parameters[index];
1806
+ auto argument = ((Type *)parameter)->subst (substitutions);
1807
+ llvm::Constant *addr =
1808
+ IGM.getAddrOfTypeMetadata (argument->getCanonicalType ());
1809
+ auto addrInt = IGF.Builder .CreateBitCast (addr, IGM.Int8PtrTy );
1810
+ condition = IGF.Builder .CreateAnd (
1811
+ condition, IGF.Builder .CreateICmpEQ (addrInt, valueAtIndex (index)));
1812
+ }
1813
+ IGF.Builder .CreateCondBr (condition, specializationBlock, successorBlock);
1814
+
1815
+ auto specializedMetadataAddress =
1816
+ IGM.getAddrOfTypeMetadata (specialization);
1817
+ // Construct a MetadataResponse. It has three fields in the following
1818
+ // order:
1819
+ // - const Metadata *Metadata;
1820
+ // - MetadataState (i32) StaticState;
1821
+ llvm::Value *response = llvm::UndefValue::get (IGM.TypeMetadataResponseTy );
1822
+ response = IGF.Builder .CreateInsertValue (
1823
+ response, specializedMetadataAddress, 0 ,
1824
+ " insert metadata address into response" );
1825
+ auto state =
1826
+ llvm::ConstantInt::get (IGM.SizeTy , (uint32_t )MetadataState::Complete);
1827
+ response = IGF.Builder .CreateInsertValue (
1828
+ response, state, 1 , " insert metadata state into response" );
1829
+ specializationBlocks.push_back ({specializationBlock, response});
1830
+ ++index;
1831
+ }
1832
+
1833
+ for (auto pair : specializationBlocks) {
1834
+ IGF.Builder .emitBlock (pair.first );
1835
+ IGF.Builder .CreateRet (pair.second );
1836
+ }
1837
+ IGF.Builder .emitBlock (switchDestination);
1838
+ }
1839
+ }
1840
+
1768
1841
static MetadataResponse
1769
1842
emitGenericTypeMetadataAccessFunction (IRGenFunction &IGF,
1770
1843
Explosion ¶ms,
@@ -1788,6 +1861,21 @@ emitGenericTypeMetadataAccessFunction(IRGenFunction &IGF,
1788
1861
llvm::Value *arguments =
1789
1862
IGF.Builder .CreateBitCast (argsBuffer.getAddress (), IGM.Int8PtrTy );
1790
1863
1864
+ llvm::Value *argumentsBuffer =
1865
+ IGF.Builder .CreateBitCast (argsBuffer.getAddress (), IGM.Int8PtrPtrTy );
1866
+
1867
+ emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction (
1868
+ IGF, params, nominal, genericArgs, [&](int index) {
1869
+ llvm::Value *indexValue = llvm::ConstantInt::get (IGM.Int64Ty , index);
1870
+ llvm::SmallVector<llvm::Value *, 1 > indices{indexValue};
1871
+ llvm::Value *elementPointer =
1872
+ IGF.Builder .CreateGEP (argumentsBuffer, indexValue);
1873
+ llvm::LoadInst *retval = IGF.Builder .CreateLoad (
1874
+ elementPointer, Alignment (),
1875
+ llvm::formatv (" load argument at index {0} from buffer" , index));
1876
+ return retval;
1877
+ });
1878
+
1791
1879
// Make the call.
1792
1880
auto call = IGF.Builder .CreateCall (IGM.getGetGenericMetadataFn (),
1793
1881
{request, arguments, descriptor});
@@ -1873,7 +1961,13 @@ emitGenericTypeMetadataAccessFunction(IRGenFunction &IGF,
1873
1961
auto arg2 = numArguments >= 3
1874
1962
? IGF.Builder .CreateBitCast (params.claimNext (), IGM.Int8PtrTy )
1875
1963
: llvm::UndefValue::get (IGM.Int8PtrTy );
1876
-
1964
+
1965
+ std::array<llvm::Value *, 3 > argValues{arg0, arg1, arg2};
1966
+
1967
+ emitCanonicalSpecializationsForGenericTypeMetadataAccessFunction (
1968
+ IGF, params, nominal, genericArgs,
1969
+ [&](int index) { return argValues[index]; });
1970
+
1877
1971
auto call = IGF.Builder .CreateCall (thunkFn,
1878
1972
{request, arg0, arg1, arg2, descriptor});
1879
1973
call->setDoesNotAccessMemory ();
0 commit comments