@@ -2660,7 +2660,19 @@ llvm::Value *irgen::loadParentProtocolWitnessTable(IRGenFunction &IGF,
2660
2660
index);
2661
2661
return baseWTable;
2662
2662
}
2663
- auto &Builder = IGF.Builder ;
2663
+
2664
+ llvm::SmallString<40 > fnName;
2665
+ llvm::raw_svector_ostream (fnName)
2666
+ << " __swift_relative_protocol_witness_table_parent_"
2667
+ << index.getValue ();
2668
+
2669
+ auto helperFn = cast<llvm::Function>(IGM.getOrCreateHelperFunction (
2670
+ fnName, IGM.WitnessTablePtrTy , {IGM.WitnessTablePtrTy },
2671
+ [&](IRGenFunction &subIGF) {
2672
+
2673
+ auto it = subIGF.CurFn ->arg_begin ();
2674
+ llvm::Value *wtable = &*it;
2675
+ auto &Builder = subIGF.Builder ;
2664
2676
auto *ptrVal = Builder.CreatePtrToInt (wtable, IGM.IntPtrTy );
2665
2677
auto *one = llvm::ConstantInt::get (IGM.IntPtrTy , 1 );
2666
2678
auto *isCond = Builder.CreateAnd (ptrVal, one);
@@ -2674,30 +2686,30 @@ llvm::Value *irgen::loadParentProtocolWitnessTable(IRGenFunction &IGF,
2674
2686
auto *mask = Builder.CreateNot (one);
2675
2687
auto *wtableAddr = Builder.CreateAnd (ptrVal, mask);
2676
2688
wtableAddr = Builder.CreateIntToPtr (wtableAddr, IGM.WitnessTablePtrTy );
2677
- auto addr = slotForLoadOfOpaqueWitness (IGF , wtableAddr, index,
2689
+ auto addr = slotForLoadOfOpaqueWitness (subIGF , wtableAddr, index,
2678
2690
false /* isRelative*/ );
2679
2691
llvm::Value *baseWTable = Builder.CreateLoad (addr);
2680
- baseWTable = IGF .Builder .CreateBitCast (baseWTable, IGF. IGM .WitnessTablePtrTy );
2692
+ baseWTable = subIGF .Builder .CreateBitCast (baseWTable, IGM.WitnessTablePtrTy );
2681
2693
Builder.CreateBr (endBB);
2682
2694
2683
2695
Builder.emitBlock (isNotCondBB);
2684
- if (auto &schema = IGF .getOptions ().PointerAuth .RelativeProtocolWitnessTable ) {
2685
- auto info = PointerAuthInfo::emit (IGF , schema, nullptr ,
2696
+ if (auto &schema = subIGF .getOptions ().PointerAuth .RelativeProtocolWitnessTable ) {
2697
+ auto info = PointerAuthInfo::emit (subIGF , schema, nullptr ,
2686
2698
PointerAuthEntity ());
2687
- wtable = emitPointerAuthAuth (IGF , wtable, info);
2699
+ wtable = emitPointerAuthAuth (subIGF , wtable, info);
2688
2700
}
2689
2701
auto baseWTable2 =
2690
- emitInvariantLoadOfOpaqueWitness (IGF ,/* isProtocolWitness*/ true , wtable,
2702
+ emitInvariantLoadOfOpaqueWitness (subIGF ,/* isProtocolWitness*/ true , wtable,
2691
2703
index);
2692
- baseWTable2 = IGF .Builder .CreateBitCast (baseWTable2,
2693
- IGF .IGM .WitnessTablePtrTy );
2694
- if (auto &schema = IGF .getOptions ().PointerAuth .RelativeProtocolWitnessTable ) {
2695
- auto info = PointerAuthInfo::emit (IGF , schema, nullptr ,
2704
+ baseWTable2 = subIGF .Builder .CreateBitCast (baseWTable2,
2705
+ subIGF .IGM .WitnessTablePtrTy );
2706
+ if (auto &schema = subIGF .getOptions ().PointerAuth .RelativeProtocolWitnessTable ) {
2707
+ auto info = PointerAuthInfo::emit (subIGF , schema, nullptr ,
2696
2708
PointerAuthEntity ());
2697
- baseWTable2 = emitPointerAuthSign (IGF , baseWTable2, info);
2709
+ baseWTable2 = emitPointerAuthSign (subIGF , baseWTable2, info);
2698
2710
2699
- baseWTable2 = IGF .Builder .CreateBitCast (baseWTable2,
2700
- IGF. IGM .WitnessTablePtrTy );
2711
+ baseWTable2 = subIGF .Builder .CreateBitCast (baseWTable2,
2712
+ IGM.WitnessTablePtrTy );
2701
2713
}
2702
2714
2703
2715
Builder.CreateBr (endBB);
@@ -2706,7 +2718,15 @@ llvm::Value *irgen::loadParentProtocolWitnessTable(IRGenFunction &IGF,
2706
2718
auto *phi = Builder.CreatePHI (wtable->getType (), 2 );
2707
2719
phi->addIncoming (baseWTable, isCondBB);
2708
2720
phi->addIncoming (baseWTable2, isNotCondBB);
2709
- return phi;
2721
+ Builder.CreateRet (phi);
2722
+
2723
+ }, true /* noinline*/ ));
2724
+
2725
+ auto *call = IGF.Builder .CreateCallWithoutDbgLoc (
2726
+ helperFn->getFunctionType (), helperFn, {wtable});
2727
+ call->setCallingConv (IGF.IGM .DefaultCC );
2728
+ call->setDoesNotThrow ();
2729
+ return call;
2710
2730
}
2711
2731
2712
2732
llvm::Value *irgen::loadConditionalConformance (IRGenFunction &IGF,
@@ -3827,6 +3847,49 @@ static llvm::Value *emitWTableSlotLoad(IRGenFunction &IGF, llvm::Value *wtable,
3827
3847
return IGF.emitInvariantLoad (slot);
3828
3848
}
3829
3849
3850
+ static FunctionPointer emitRelativeProtocolWitnessTableAccess (IRGenFunction &IGF,
3851
+ WitnessIndex index,
3852
+ llvm::Value *wtable,
3853
+ SILDeclRef member) {
3854
+ auto witnessTableTy = wtable->getType ();
3855
+ auto &IGM = IGF.IGM ;
3856
+ llvm::SmallString<40 > fnName;
3857
+ auto entity = LinkEntity::forMethodDescriptor (member);
3858
+ auto mangled = entity.mangleAsString ();
3859
+ llvm::raw_svector_ostream (fnName)
3860
+ << " __swift_relative_protocol_witness_table_access_"
3861
+ << index.forProtocolWitnessTable ().getValue ()
3862
+ << " _" << mangled;
3863
+
3864
+ auto fnType = IGF.IGM .getSILTypes ().getConstantFunctionType (
3865
+ IGF.IGM .getMaximalTypeExpansionContext (), member);
3866
+ Signature signature = IGF.IGM .getSignature (fnType);
3867
+
3868
+ auto helperFn = cast<llvm::Function>(IGM.getOrCreateHelperFunction (
3869
+ fnName, IGM.Int8PtrTy , {witnessTableTy},
3870
+ [&](IRGenFunction &subIGF) {
3871
+
3872
+ auto it = subIGF.CurFn ->arg_begin ();
3873
+ llvm::Value *wtable = &*it;
3874
+ wtable = subIGF.optionallyLoadFromConditionalProtocolWitnessTable (wtable);
3875
+ auto slot = slotForLoadOfOpaqueWitness (subIGF, wtable,
3876
+ index.forProtocolWitnessTable (),
3877
+ true );
3878
+ llvm::Value *witnessFnPtr = emitWTableSlotLoad (subIGF, wtable, member, slot,
3879
+ true );
3880
+
3881
+ subIGF.Builder .CreateRet (witnessFnPtr);
3882
+
3883
+ }, true /* noinline*/ ));
3884
+
3885
+ auto *call = IGF.Builder .CreateCallWithoutDbgLoc (
3886
+ helperFn->getFunctionType (), helperFn, {wtable});
3887
+ call->setCallingConv (IGF.IGM .DefaultCC );
3888
+ call->setDoesNotThrow ();
3889
+ auto fn = IGF.Builder .CreateBitCast (call, signature.getType ()->getPointerTo ());
3890
+ return FunctionPointer::createUnsigned (fnType, fn, signature, true );
3891
+ }
3892
+
3830
3893
FunctionPointer irgen::emitWitnessMethodValue (IRGenFunction &IGF,
3831
3894
llvm::Value *wtable,
3832
3895
SILDeclRef member) {
@@ -3839,22 +3902,22 @@ FunctionPointer irgen::emitWitnessMethodValue(IRGenFunction &IGF,
3839
3902
auto &fnProtoInfo = IGF.IGM .getProtocolInfo (proto, ProtocolInfoKind::Full);
3840
3903
auto index = fnProtoInfo.getFunctionIndex (member);
3841
3904
auto isRelativeTable = IGF.IGM .IRGen .Opts .UseRelativeProtocolWitnessTables ;
3905
+ if (isRelativeTable) {
3906
+ return emitRelativeProtocolWitnessTableAccess (IGF, index, wtable, member);
3907
+ }
3908
+
3842
3909
wtable = IGF.optionallyLoadFromConditionalProtocolWitnessTable (wtable);
3843
3910
auto slot =
3844
3911
slotForLoadOfOpaqueWitness (IGF, wtable, index.forProtocolWitnessTable (),
3845
- isRelativeTable);
3912
+ false /* isRelativeTable*/ );
3846
3913
llvm::Value *witnessFnPtr = emitWTableSlotLoad (IGF, wtable, member, slot,
3847
- isRelativeTable);
3914
+ false /* isRelativeTable*/ );
3848
3915
3849
3916
auto fnType = IGF.IGM .getSILTypes ().getConstantFunctionType (
3850
3917
IGF.IGM .getMaximalTypeExpansionContext (), member);
3851
3918
Signature signature = IGF.IGM .getSignature (fnType);
3852
3919
witnessFnPtr = IGF.Builder .CreateBitCast (witnessFnPtr,
3853
3920
signature.getType ()->getPointerTo ());
3854
- if (isRelativeTable) {
3855
- return FunctionPointer::createUnsigned (fnType, witnessFnPtr, signature,
3856
- true );
3857
- }
3858
3921
3859
3922
auto &schema = fnType->isAsync ()
3860
3923
? IGF.getOptions ().PointerAuth .AsyncProtocolWitnesses
0 commit comments