18
18
#include " swift/AST/Types.h"
19
19
#include " swift/Demangling/Demangler.h"
20
20
#include " swift/Demangling/ManglingMacros.h"
21
+ #include " swift/SIL/ApplySite.h"
21
22
#include " swift/SIL/DebugUtils.h"
22
23
#include " swift/SIL/DynamicCasts.h"
23
24
#include " swift/SIL/SILArgument.h"
24
25
#include " swift/SIL/SILBuilder.h"
25
26
#include " swift/SIL/SILFunction.h"
26
- #include " swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
27
27
#include " swift/SIL/SILInstruction.h"
28
28
#include " swift/SIL/SILModule.h"
29
29
#include " swift/SILOptimizer/PassManager/Passes.h"
30
30
#include " swift/SILOptimizer/PassManager/Transforms.h"
31
+ #include " swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
31
32
#include " llvm/ADT/BitVector.h"
32
33
#include " llvm/Support/CommandLine.h"
33
34
#include " llvm/Support/raw_ostream.h"
@@ -50,20 +51,23 @@ class OutlinerMangler : public Mangle::ASTMangler {
50
51
};
51
52
52
53
llvm::BitVector *IsParameterBridged;
54
+ llvm::BitVector *IsParameterGuaranteed;
53
55
SILDeclRef MethodDecl;
54
56
MethodKind Kind;
55
57
bool IsReturnBridged;
56
58
57
59
public:
58
60
// / Create an mangler for an outlined bridged method.
59
61
OutlinerMangler (SILDeclRef Method, llvm::BitVector *ParameterBridged,
60
- bool ReturnBridged)
61
- : IsParameterBridged(ParameterBridged), MethodDecl(Method),
62
+ llvm::BitVector *IsParameterGuaranteed, bool ReturnBridged)
63
+ : IsParameterBridged(ParameterBridged),
64
+ IsParameterGuaranteed (IsParameterGuaranteed), MethodDecl(Method),
62
65
Kind(BridgedMethod), IsReturnBridged(ReturnBridged) {}
63
66
64
67
// / Create an mangler for an outlined bridged property.
65
68
OutlinerMangler (SILDeclRef Method, bool IsAddress)
66
- : IsParameterBridged(nullptr ), MethodDecl(Method),
69
+ : IsParameterBridged(nullptr ), IsParameterGuaranteed(nullptr ),
70
+ MethodDecl(Method),
67
71
Kind(IsAddress ? BridgedPropertyAddress : BridgedProperty),
68
72
IsReturnBridged(true ) {}
69
73
@@ -93,9 +97,14 @@ std::string OutlinerMangler::mangle() {
93
97
llvm::raw_svector_ostream Out (Buffer);
94
98
95
99
Out << getMethodKindMangling ();
96
- if (IsParameterBridged)
97
- for (unsigned Idx = 0 , E = IsParameterBridged->size (); Idx != E; ++Idx)
100
+ if (IsParameterBridged) {
101
+ for (unsigned Idx = 0 , E = IsParameterBridged->size (); Idx != E; ++Idx) {
98
102
Out << (IsParameterBridged->test (Idx) ? ' b' : ' n' );
103
+ // NOTE: We must keep owned as having nothing here to preserve ABI since
104
+ // mangling is part of ABI.
105
+ Out << (IsParameterGuaranteed->test (Idx) ? " g" : " " );
106
+ }
107
+ }
99
108
Out << (IsReturnBridged ? ' b' : ' n' );
100
109
Out << ' _' ;
101
110
@@ -643,7 +652,10 @@ bool BridgedProperty::matchInstSequence(SILBasicBlock::iterator It) {
643
652
644
653
645
654
namespace {
655
+
646
656
// / Match a bridged argument.
657
+ // /
658
+ // /
647
659
// / %15 = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
648
660
// / %16 = apply %15(%14) :
649
661
// / $@convention(method) (@guaranteed String) -> @owned NSString
@@ -652,20 +664,26 @@ namespace {
652
664
// /
653
665
// / apply %objcMethod(%17, ...) : $@convention(objc_method) (Optional<NSString> ...) ->
654
666
// / release_value %17 : $Optional<NSString>
667
+ // /
668
+ // / NOTE: If release_value %14 is found, our outlined function will have an
669
+ // / owned convention for self. Otherwise, if we do not find it, we will have a
670
+ // / guaranteed one.
655
671
class BridgedArgument {
656
672
public:
657
673
FunctionRefInst *BridgeFun;
658
674
ApplyInst *BridgeCall;
659
675
EnumInst *OptionalResult;
676
+ SILValue BridgedValue;
660
677
ReleaseValueInst *ReleaseAfterBridge;
661
678
ReleaseValueInst *ReleaseArgAfterCall;
662
679
unsigned Idx = 0 ;
663
680
664
681
// Matched bridged argument.
665
682
BridgedArgument (unsigned Idx, FunctionRefInst *F, ApplyInst *A, EnumInst *E,
666
683
ReleaseValueInst *R0, ReleaseValueInst *R1)
667
- : BridgeFun(F), BridgeCall(A), OptionalResult(E), ReleaseAfterBridge(R0),
668
- ReleaseArgAfterCall (R1), Idx(Idx) {}
684
+ : BridgeFun(F), BridgeCall(A), OptionalResult(E),
685
+ BridgedValue (FullApplySite(A).getSelfArgument()),
686
+ ReleaseAfterBridge(R0), ReleaseArgAfterCall(R1), Idx(Idx) {}
669
687
670
688
// / Invalid argument constructor.
671
689
BridgedArgument ()
@@ -675,7 +693,14 @@ class BridgedArgument {
675
693
static BridgedArgument match (unsigned ArgIdx, SILValue Arg, ApplyInst *AI);
676
694
677
695
operator bool () const { return BridgeFun != nullptr ; }
678
- SILValue bridgedValue () { return ReleaseAfterBridge->getOperand (); }
696
+ SILValue bridgedValue () { return BridgedValue; }
697
+
698
+ bool isGuaranteed () const { return ReleaseAfterBridge == nullptr ; }
699
+ ParameterConvention getConvention () const {
700
+ if (isGuaranteed ())
701
+ return ParameterConvention::Direct_Guaranteed;
702
+ return ParameterConvention::Direct_Owned;
703
+ }
679
704
680
705
void eraseFromParent ();
681
706
@@ -697,14 +722,17 @@ void BridgedArgument::transferTo(SILValue BridgedValue,
697
722
DestBB->moveTo (SILBasicBlock::iterator (BridgedCall), BridgeCall);
698
723
BridgeCall->setArgument (0 , BridgedValue);
699
724
DestBB->moveTo (SILBasicBlock::iterator (BridgedCall), OptionalResult);
700
- DestBB->moveTo (SILBasicBlock::iterator (BridgedCall), ReleaseAfterBridge);
701
- ReleaseAfterBridge->setOperand (BridgedValue);
725
+ if (ReleaseAfterBridge) {
726
+ DestBB->moveTo (SILBasicBlock::iterator (BridgedCall), ReleaseAfterBridge);
727
+ ReleaseAfterBridge->setOperand (BridgedValue);
728
+ }
702
729
auto AfterCall = std::next (SILBasicBlock::iterator (BridgedCall));
703
730
DestBB->moveTo (SILBasicBlock::iterator (AfterCall), ReleaseArgAfterCall);
704
731
}
705
732
706
733
void BridgedArgument::eraseFromParent () {
707
- ReleaseAfterBridge->eraseFromParent ();
734
+ if (ReleaseAfterBridge)
735
+ ReleaseAfterBridge->eraseFromParent ();
708
736
ReleaseArgAfterCall->eraseFromParent ();
709
737
OptionalResult->eraseFromParent ();
710
738
BridgeCall->eraseFromParent ();
@@ -740,9 +768,12 @@ BridgedArgument BridgedArgument::match(unsigned ArgIdx, SILValue Arg,
740
768
auto Next = std::next (SILBasicBlock::iterator (Enum));
741
769
if (Next == Enum->getParent ()->end ())
742
770
return BridgedArgument ();
771
+
772
+ // Make sure that if we have a bridged value release that it is on the bridged
773
+ // value.
743
774
auto *BridgedValueRelease =
744
775
dyn_cast<ReleaseValueInst>(std::next (SILBasicBlock::iterator (Enum)));
745
- if (! BridgedValueRelease || BridgedValueRelease->getOperand () != BridgedValue)
776
+ if (BridgedValueRelease && BridgedValueRelease->getOperand () != BridgedValue)
746
777
return BridgedArgument ();
747
778
748
779
if (SILBasicBlock::iterator (BridgeCall) == BridgeCall->getParent ()->begin ())
@@ -885,6 +916,7 @@ class ObjCMethodCall : public OutlinePattern {
885
916
SmallVector<BridgedArgument, 4 > BridgedArguments;
886
917
std::string OutlinedName;
887
918
llvm::BitVector IsBridgedArgument;
919
+ llvm::BitVector IsGuaranteedArgument;
888
920
BridgedReturn BridgedReturn;
889
921
public:
890
922
bool matchInstSequence (SILBasicBlock::iterator I) override ;
@@ -913,6 +945,7 @@ void ObjCMethodCall::clearState() {
913
945
BridgedArguments.clear ();
914
946
OutlinedName.clear ();
915
947
IsBridgedArgument.clear ();
948
+ IsGuaranteedArgument.clear ();
916
949
}
917
950
918
951
std::pair<SILFunction *, SILBasicBlock::iterator>
@@ -1018,7 +1051,7 @@ ObjCMethodCall::outline(SILModule &M) {
1018
1051
std::string ObjCMethodCall::getOutlinedFunctionName () {
1019
1052
if (OutlinedName.empty ()) {
1020
1053
OutlinerMangler Mangler (ObjCMethod->getMember (), &IsBridgedArgument,
1021
- BridgedReturn);
1054
+ &IsGuaranteedArgument, BridgedReturn);
1022
1055
OutlinedName = Mangler.mangle ();
1023
1056
}
1024
1057
return OutlinedName;
@@ -1046,6 +1079,7 @@ bool ObjCMethodCall::matchInstSequence(SILBasicBlock::iterator I) {
1046
1079
// Collect bridged parameters.
1047
1080
unsigned Idx = 0 ;
1048
1081
IsBridgedArgument.resize (BridgedCall->getNumArguments (), false );
1082
+ IsGuaranteedArgument.resize (BridgedCall->getNumArguments (), false );
1049
1083
for (auto &Param : BridgedCall->getArgumentOperands ()) {
1050
1084
unsigned CurIdx = Idx++;
1051
1085
@@ -1066,6 +1100,8 @@ bool ObjCMethodCall::matchInstSequence(SILBasicBlock::iterator I) {
1066
1100
1067
1101
BridgedArguments.push_back (BridgedArg);
1068
1102
IsBridgedArgument.set (CurIdx);
1103
+ if (BridgedArg.isGuaranteed ())
1104
+ IsGuaranteedArgument.set (CurIdx);
1069
1105
}
1070
1106
1071
1107
// Try to match a bridged return value.
@@ -1097,11 +1133,12 @@ CanSILFunctionType ObjCMethodCall::getOutlinedFunctionType(SILModule &M) {
1097
1133
// Either use the bridged type passing it @owned.
1098
1134
if (BridgedArgIdx < BridgedArguments.size () &&
1099
1135
BridgedArguments[BridgedArgIdx].Idx == OrigSigIdx) {
1136
+ auto convention = BridgedArguments[BridgedArgIdx].getConvention ();
1100
1137
Parameters.push_back (SILParameterInfo (BridgedArguments[BridgedArgIdx]
1101
1138
.bridgedValue ()
1102
1139
->getType ()
1103
1140
.getASTType (),
1104
- ParameterConvention::Direct_Owned ));
1141
+ convention ));
1105
1142
++BridgedArgIdx;
1106
1143
} else {
1107
1144
// Otherwise, use the original type convention.
0 commit comments