28
28
#include " GenericRequirement.h"
29
29
#include " IRGenDebugInfo.h"
30
30
#include " IRGenFunction.h"
31
+ #include " IRGenMangler.h"
31
32
#include " IRGenModule.h"
32
33
#include " MetadataLayout.h"
33
34
#include " ProtocolInfo.h"
@@ -649,53 +650,83 @@ getInitializerForComputedComponent(IRGenModule &IGM,
649
650
// / protocol conformance metadata record.
650
651
// / TODO: It would be much better to emit typeref strings and use runtime
651
652
// / demangling here.
652
- static llvm::Function *
653
+ static llvm::Constant *
653
654
emitGeneratorForKeyPath (IRGenModule &IGM,
654
655
StringRef name, CanType type, llvm::Type *returnType,
655
656
GenericEnvironment *genericEnv,
656
657
ArrayRef<GenericRequirement> requirements,
657
658
llvm::function_ref<void (IRGenFunction&,CanType)> emit) {
658
- // TODO: Use the standard metadata accessor when there are no arguments
659
- // and the metadata accessor is defined.
660
659
661
- // Build a stub that loads the necessary bindings from the key path's
662
- // argument buffer then fetches the metadata.
663
- auto fnTy = llvm::FunctionType::get (returnType,
664
- {IGM.Int8PtrTy }, /* vararg*/ false );
665
- auto accessorThunk = llvm::Function::Create (fnTy,
666
- llvm::GlobalValue::PrivateLinkage,
667
- name, IGM.getModule ());
668
- accessorThunk->setAttributes (IGM.constructInitialAttributes ());
669
- {
670
- IRGenFunction IGF (IGM, accessorThunk);
671
- if (IGM.DebugInfo )
672
- IGM.DebugInfo ->emitArtificialFunction (IGF, accessorThunk);
673
-
674
- if (type->hasTypeParameter ()) {
675
- auto bindingsBufPtr = IGF.collectParameters ().claimNext ();
676
-
677
- bindFromGenericRequirementsBuffer (IGF, requirements,
678
- Address (bindingsBufPtr, IGM.getPointerAlignment ()),
679
- MetadataState::Complete,
680
- [&](CanType t) {
681
- return genericEnv->mapTypeIntoContext (t)->getCanonicalType ();
682
- });
683
-
684
- type = genericEnv->mapTypeIntoContext (type)->getCanonicalType ();
685
- }
686
- emit (IGF, type);
687
- }
688
- return accessorThunk;
660
+ return IGM.getAddrOfStringForMetadataRef (name,
661
+ /* shouldSetLowBit=*/ true ,
662
+ [&](ConstantInitBuilder &B) {
663
+ // Build a stub that loads the necessary bindings from the key path's
664
+ // argument buffer then fetches the metadata.
665
+ auto fnTy = llvm::FunctionType::get (returnType,
666
+ {IGM.Int8PtrTy }, /* vararg*/ false );
667
+ auto accessorThunk =
668
+ llvm::Function::Create (fnTy, llvm::GlobalValue::PrivateLinkage,
669
+ name, IGM.getModule ());
670
+ accessorThunk->setAttributes (IGM.constructInitialAttributes ());
671
+ {
672
+ IRGenFunction IGF (IGM, accessorThunk);
673
+ if (IGM.DebugInfo )
674
+ IGM.DebugInfo ->emitArtificialFunction (IGF, accessorThunk);
675
+
676
+ if (type->hasTypeParameter ()) {
677
+ auto bindingsBufPtr = IGF.collectParameters ().claimNext ();
678
+
679
+ bindFromGenericRequirementsBuffer (IGF, requirements,
680
+ Address (bindingsBufPtr, IGM.getPointerAlignment ()),
681
+ MetadataState::Complete,
682
+ [&](CanType t) {
683
+ return genericEnv->mapTypeIntoContext (t)->getCanonicalType ();
684
+ });
685
+
686
+ type = genericEnv->mapTypeIntoContext (type)->getCanonicalType ();
687
+ }
688
+ emit (IGF, type);
689
+ }
690
+
691
+ // Form the mangled name with its relative reference.
692
+ auto S = B.beginStruct ();
693
+ S.setPacked (true );
694
+ S.add (llvm::ConstantInt::get (IGM.Int8Ty , 9 ));
695
+ S.addRelativeAddress (accessorThunk);
696
+
697
+ // And a null terminator!
698
+ S.addInt (IGM.Int8Ty , 0 );
699
+
700
+ return S.finishAndCreateFuture ();
701
+ });
689
702
}
690
703
691
- static llvm::Function *
704
+ static llvm::Constant *
692
705
emitMetadataGeneratorForKeyPath (IRGenModule &IGM,
693
706
CanType type,
694
707
GenericEnvironment *genericEnv,
695
708
ArrayRef<GenericRequirement> requirements) {
709
+ // If we have a non-dependent type, use a normal mangled type name.
710
+ if (!type->hasTypeParameter ()) {
711
+ auto constant = IGM.getTypeRef (type, MangledTypeRefRole::Metadata);
712
+ auto bitConstant = llvm::ConstantInt::get (IGM.IntPtrTy , 1 );
713
+ return llvm::ConstantExpr::getGetElementPtr (nullptr , constant, bitConstant);
714
+ }
715
+
716
+ // Otherwise, create an accessor.
717
+ CanGenericSignature genericSig;
718
+ if (genericEnv)
719
+ genericSig = genericEnv->getGenericSignature ()->getCanonicalSignature ();
720
+
721
+ IRGenMangler mangler;
722
+ std::string symbolName =
723
+ mangler.mangleSymbolNameForKeyPathMetadata (
724
+ " keypath_get_type" , genericSig, type,
725
+ ProtocolConformanceRef::forInvalid ());
726
+
696
727
// TODO: Use the standard metadata accessor when there are no arguments
697
728
// and the metadata accessor is defined.
698
- return emitGeneratorForKeyPath (IGM, " keypath_get_type " , type,
729
+ return emitGeneratorForKeyPath (IGM, symbolName , type,
699
730
IGM.TypeMetadataPtrTy ,
700
731
genericEnv, requirements,
701
732
[&](IRGenFunction &IGF, CanType substType) {
@@ -704,15 +735,24 @@ emitMetadataGeneratorForKeyPath(IRGenModule &IGM,
704
735
});
705
736
};
706
737
707
- static llvm::Function *
738
+ static llvm::Constant *
708
739
emitWitnessTableGeneratorForKeyPath (IRGenModule &IGM,
709
740
CanType type,
710
741
ProtocolConformanceRef conformance,
711
742
GenericEnvironment *genericEnv,
712
743
ArrayRef<GenericRequirement> requirements) {
744
+ CanGenericSignature genericSig;
745
+ if (genericEnv)
746
+ genericSig = genericEnv->getGenericSignature ()->getCanonicalSignature ();
747
+
748
+ IRGenMangler mangler;
749
+ std::string symbolName =
750
+ mangler.mangleSymbolNameForKeyPathMetadata (
751
+ " keypath_get_witness_table" , genericSig, type, conformance);
752
+
713
753
// TODO: Use the standard conformance accessor when there are no arguments
714
754
// and the conformance accessor is defined.
715
- return emitGeneratorForKeyPath (IGM, " keypath_get_witness_table " , type,
755
+ return emitGeneratorForKeyPath (IGM, symbolName , type,
716
756
IGM.WitnessTablePtrTy ,
717
757
genericEnv, requirements,
718
758
[&](IRGenFunction &IGF, CanType substType) {
0 commit comments