Skip to content

Commit d6e30b5

Browse files
committed
[outliner] Add support for passing bridging args as guaranteed if we do not find a release.
1 parent 343b400 commit d6e30b5

File tree

3 files changed

+54
-16
lines changed

3 files changed

+54
-16
lines changed

lib/Demangling/Demangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2339,7 +2339,7 @@ std::string Demangler::demangleBridgedMethodParams() {
23392339

23402340
while (!nextIf('_')) {
23412341
auto c = nextChar();
2342-
if (c != 'n' && c != 'b')
2342+
if (c != 'n' && c != 'b' && c != 'g')
23432343
return std::string();
23442344
Str.push_back(c);
23452345
}

lib/SILOptimizer/Transforms/Outliner.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,17 @@
1818
#include "swift/AST/Types.h"
1919
#include "swift/Demangling/Demangler.h"
2020
#include "swift/Demangling/ManglingMacros.h"
21+
#include "swift/SIL/ApplySite.h"
2122
#include "swift/SIL/DebugUtils.h"
2223
#include "swift/SIL/DynamicCasts.h"
2324
#include "swift/SIL/SILArgument.h"
2425
#include "swift/SIL/SILBuilder.h"
2526
#include "swift/SIL/SILFunction.h"
26-
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
2727
#include "swift/SIL/SILInstruction.h"
2828
#include "swift/SIL/SILModule.h"
2929
#include "swift/SILOptimizer/PassManager/Passes.h"
3030
#include "swift/SILOptimizer/PassManager/Transforms.h"
31+
#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h"
3132
#include "llvm/ADT/BitVector.h"
3233
#include "llvm/Support/CommandLine.h"
3334
#include "llvm/Support/raw_ostream.h"
@@ -50,20 +51,23 @@ class OutlinerMangler : public Mangle::ASTMangler {
5051
};
5152

5253
llvm::BitVector *IsParameterBridged;
54+
llvm::BitVector *IsParameterGuaranteed;
5355
SILDeclRef MethodDecl;
5456
MethodKind Kind;
5557
bool IsReturnBridged;
5658

5759
public:
5860
/// Create an mangler for an outlined bridged method.
5961
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),
6265
Kind(BridgedMethod), IsReturnBridged(ReturnBridged) {}
6366

6467
/// Create an mangler for an outlined bridged property.
6568
OutlinerMangler(SILDeclRef Method, bool IsAddress)
66-
: IsParameterBridged(nullptr), MethodDecl(Method),
69+
: IsParameterBridged(nullptr), IsParameterGuaranteed(nullptr),
70+
MethodDecl(Method),
6771
Kind(IsAddress ? BridgedPropertyAddress : BridgedProperty),
6872
IsReturnBridged(true) {}
6973

@@ -93,9 +97,14 @@ std::string OutlinerMangler::mangle() {
9397
llvm::raw_svector_ostream Out(Buffer);
9498

9599
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) {
98102
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+
}
99108
Out << (IsReturnBridged ? 'b' : 'n');
100109
Out << '_';
101110

@@ -643,7 +652,10 @@ bool BridgedProperty::matchInstSequence(SILBasicBlock::iterator It) {
643652

644653

645654
namespace {
655+
646656
/// Match a bridged argument.
657+
///
658+
///
647659
/// %15 = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
648660
/// %16 = apply %15(%14) :
649661
/// $@convention(method) (@guaranteed String) -> @owned NSString
@@ -652,20 +664,26 @@ namespace {
652664
///
653665
/// apply %objcMethod(%17, ...) : $@convention(objc_method) (Optional<NSString> ...) ->
654666
/// 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.
655671
class BridgedArgument {
656672
public:
657673
FunctionRefInst *BridgeFun;
658674
ApplyInst *BridgeCall;
659675
EnumInst *OptionalResult;
676+
SILValue BridgedValue;
660677
ReleaseValueInst *ReleaseAfterBridge;
661678
ReleaseValueInst *ReleaseArgAfterCall;
662679
unsigned Idx = 0;
663680

664681
// Matched bridged argument.
665682
BridgedArgument(unsigned Idx, FunctionRefInst *F, ApplyInst *A, EnumInst *E,
666683
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) {}
669687

670688
/// Invalid argument constructor.
671689
BridgedArgument()
@@ -675,7 +693,14 @@ class BridgedArgument {
675693
static BridgedArgument match(unsigned ArgIdx, SILValue Arg, ApplyInst *AI);
676694

677695
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+
}
679704

680705
void eraseFromParent();
681706

@@ -697,14 +722,17 @@ void BridgedArgument::transferTo(SILValue BridgedValue,
697722
DestBB->moveTo(SILBasicBlock::iterator(BridgedCall), BridgeCall);
698723
BridgeCall->setArgument(0, BridgedValue);
699724
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+
}
702729
auto AfterCall = std::next(SILBasicBlock::iterator(BridgedCall));
703730
DestBB->moveTo(SILBasicBlock::iterator(AfterCall), ReleaseArgAfterCall);
704731
}
705732

706733
void BridgedArgument::eraseFromParent() {
707-
ReleaseAfterBridge->eraseFromParent();
734+
if (ReleaseAfterBridge)
735+
ReleaseAfterBridge->eraseFromParent();
708736
ReleaseArgAfterCall->eraseFromParent();
709737
OptionalResult->eraseFromParent();
710738
BridgeCall->eraseFromParent();
@@ -740,9 +768,12 @@ BridgedArgument BridgedArgument::match(unsigned ArgIdx, SILValue Arg,
740768
auto Next = std::next(SILBasicBlock::iterator(Enum));
741769
if (Next == Enum->getParent()->end())
742770
return BridgedArgument();
771+
772+
// Make sure that if we have a bridged value release that it is on the bridged
773+
// value.
743774
auto *BridgedValueRelease =
744775
dyn_cast<ReleaseValueInst>(std::next(SILBasicBlock::iterator(Enum)));
745-
if (!BridgedValueRelease || BridgedValueRelease->getOperand() != BridgedValue)
776+
if (BridgedValueRelease && BridgedValueRelease->getOperand() != BridgedValue)
746777
return BridgedArgument();
747778

748779
if (SILBasicBlock::iterator(BridgeCall) == BridgeCall->getParent()->begin())
@@ -885,6 +916,7 @@ class ObjCMethodCall : public OutlinePattern {
885916
SmallVector<BridgedArgument, 4> BridgedArguments;
886917
std::string OutlinedName;
887918
llvm::BitVector IsBridgedArgument;
919+
llvm::BitVector IsGuaranteedArgument;
888920
BridgedReturn BridgedReturn;
889921
public:
890922
bool matchInstSequence(SILBasicBlock::iterator I) override;
@@ -913,6 +945,7 @@ void ObjCMethodCall::clearState() {
913945
BridgedArguments.clear();
914946
OutlinedName.clear();
915947
IsBridgedArgument.clear();
948+
IsGuaranteedArgument.clear();
916949
}
917950

918951
std::pair<SILFunction *, SILBasicBlock::iterator>
@@ -1018,7 +1051,7 @@ ObjCMethodCall::outline(SILModule &M) {
10181051
std::string ObjCMethodCall::getOutlinedFunctionName() {
10191052
if (OutlinedName.empty()) {
10201053
OutlinerMangler Mangler(ObjCMethod->getMember(), &IsBridgedArgument,
1021-
BridgedReturn);
1054+
&IsGuaranteedArgument, BridgedReturn);
10221055
OutlinedName = Mangler.mangle();
10231056
}
10241057
return OutlinedName;
@@ -1046,6 +1079,7 @@ bool ObjCMethodCall::matchInstSequence(SILBasicBlock::iterator I) {
10461079
// Collect bridged parameters.
10471080
unsigned Idx = 0;
10481081
IsBridgedArgument.resize(BridgedCall->getNumArguments(), false);
1082+
IsGuaranteedArgument.resize(BridgedCall->getNumArguments(), false);
10491083
for (auto &Param : BridgedCall->getArgumentOperands()) {
10501084
unsigned CurIdx = Idx++;
10511085

@@ -1066,6 +1100,8 @@ bool ObjCMethodCall::matchInstSequence(SILBasicBlock::iterator I) {
10661100

10671101
BridgedArguments.push_back(BridgedArg);
10681102
IsBridgedArgument.set(CurIdx);
1103+
if (BridgedArg.isGuaranteed())
1104+
IsGuaranteedArgument.set(CurIdx);
10691105
}
10701106

10711107
// Try to match a bridged return value.
@@ -1097,11 +1133,12 @@ CanSILFunctionType ObjCMethodCall::getOutlinedFunctionType(SILModule &M) {
10971133
// Either use the bridged type passing it @owned.
10981134
if (BridgedArgIdx < BridgedArguments.size() &&
10991135
BridgedArguments[BridgedArgIdx].Idx == OrigSigIdx) {
1136+
auto convention = BridgedArguments[BridgedArgIdx].getConvention();
11001137
Parameters.push_back(SILParameterInfo(BridgedArguments[BridgedArgIdx]
11011138
.bridgedValue()
11021139
->getType()
11031140
.getASTType(),
1104-
ParameterConvention::Direct_Owned));
1141+
convention));
11051142
++BridgedArgIdx;
11061143
} else {
11071144
// Otherwise, use the original type convention.

test/Demangle/Inputs/manglings.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ _T03nix6testitSaySiGyFTv_ ---> outlined variable #0 of nix.testit() -> [Swift.In
293293
_T03nix6testitSaySiGyFTv0_ ---> outlined variable #1 of nix.testit() -> [Swift.Int]
294294
_T0So11UITextFieldC4textSSSgvgToTepb_ ---> outlined bridged method (pb) of @objc __C.UITextField.text.getter : Swift.String?
295295
_T0So11UITextFieldC4textSSSgvgToTeab_ ---> outlined bridged method (ab) of @objc __C.UITextField.text.getter : Swift.String?
296+
$sSo5GizmoC11doSomethingyypSgSaySSGSgFToTembgnn_ ---> outlined bridged method (mbgnn) of @objc __C.Gizmo.doSomething([Swift.String]?) -> Any?
296297
_T04test1SVyxGAA1RA2A1ZRzAA1Y2ZZRpzl1A_AhaGPWT ---> {C} associated type witness table accessor for A.ZZ : test.Y in <A where A: test.Z, A.ZZ: test.Y> test.S<A> : test.R in test
297298
_T0s24_UnicodeScalarExceptions33_0E4228093681F6920F0AB2E48B4F1C69LLVACycfC ---> {T:_T0s24_UnicodeScalarExceptions33_0E4228093681F6920F0AB2E48B4F1C69LLVACycfc} Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69).init() -> Swift.(_UnicodeScalarExceptions in _0E4228093681F6920F0AB2E48B4F1C69)
298299
_T0D ---> _T0D

0 commit comments

Comments
 (0)