Skip to content

Commit d60af18

Browse files
authored
Merge pull request #19964 from rjmccall/builtin-ownership
Emit certain builtin arguments as owned values
2 parents 281ad7e + 3a7c649 commit d60af18

File tree

11 files changed

+178
-134
lines changed

11 files changed

+178
-134
lines changed

include/swift/AST/Decl.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4699,7 +4699,11 @@ class VarDecl : public AbstractStorageDecl {
46994699
bool isOwned() const { return getSpecifier() == Specifier::Owned; }
47004700

47014701
ValueOwnership getValueOwnership() const {
4702-
switch (getSpecifier()) {
4702+
return getValueOwnershipForSpecifier(getSpecifier());
4703+
}
4704+
4705+
static ValueOwnership getValueOwnershipForSpecifier(Specifier specifier) {
4706+
switch (specifier) {
47034707
case Specifier::Let:
47044708
return ValueOwnership::Default;
47054709
case Specifier::Var:
@@ -4714,6 +4718,21 @@ class VarDecl : public AbstractStorageDecl {
47144718
llvm_unreachable("unhandled specifier");
47154719
}
47164720

4721+
static Specifier
4722+
getParameterSpecifierForValueOwnership(ValueOwnership ownership) {
4723+
switch (ownership) {
4724+
case ValueOwnership::Default:
4725+
return Specifier::Let;
4726+
case ValueOwnership::Shared:
4727+
return Specifier::Shared;
4728+
case ValueOwnership::InOut:
4729+
return Specifier::InOut;
4730+
case ValueOwnership::Owned:
4731+
return Specifier::Owned;
4732+
}
4733+
llvm_unreachable("unhandled ownership");
4734+
}
4735+
47174736
/// Is this an element in a capture list?
47184737
bool isCaptureList() const { return Bits.VarDecl.IsCaptureList; }
47194738

include/swift/AST/Types.h

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,9 +1658,8 @@ class ParameterTypeFlags {
16581658
Variadic = 1 << 0,
16591659
AutoClosure = 1 << 1,
16601660
Escaping = 1 << 2,
1661-
InOut = 1 << 3,
1662-
Shared = 1 << 4,
1663-
Owned = 1 << 5,
1661+
OwnershipShift = 3,
1662+
Ownership = 7 << OwnershipShift,
16641663

16651664
NumBits = 6
16661665
};
@@ -1679,9 +1678,7 @@ class ParameterTypeFlags {
16791678
ValueOwnership ownership)
16801679
: value((variadic ? Variadic : 0) | (autoclosure ? AutoClosure : 0) |
16811680
(escaping ? Escaping : 0) |
1682-
(ownership == ValueOwnership::InOut ? InOut : 0) |
1683-
(ownership == ValueOwnership::Shared ? Shared : 0) |
1684-
(ownership == ValueOwnership::Owned ? Owned : 0)) {}
1681+
uint8_t(ownership) << OwnershipShift) {}
16851682

16861683
/// Create one from what's present in the parameter type
16871684
inline static ParameterTypeFlags
@@ -1691,19 +1688,12 @@ class ParameterTypeFlags {
16911688
bool isVariadic() const { return value.contains(Variadic); }
16921689
bool isAutoClosure() const { return value.contains(AutoClosure); }
16931690
bool isEscaping() const { return value.contains(Escaping); }
1694-
bool isInOut() const { return value.contains(InOut); }
1695-
bool isShared() const { return value.contains(Shared); }
1696-
bool isOwned() const { return value.contains(Owned); }
1691+
bool isInOut() const { return getValueOwnership() == ValueOwnership::InOut; }
1692+
bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;}
1693+
bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; }
16971694

16981695
ValueOwnership getValueOwnership() const {
1699-
if (isInOut())
1700-
return ValueOwnership::InOut;
1701-
else if (isShared())
1702-
return ValueOwnership::Shared;
1703-
else if (isOwned())
1704-
return ValueOwnership::Owned;
1705-
1706-
return ValueOwnership::Default;
1696+
return ValueOwnership((value.toRaw() & Ownership) >> OwnershipShift);
17071697
}
17081698

17091699
ParameterTypeFlags withVariadic(bool variadic) const {
@@ -1717,18 +1707,23 @@ class ParameterTypeFlags {
17171707
}
17181708

17191709
ParameterTypeFlags withInOut(bool isInout) const {
1720-
return ParameterTypeFlags(isInout ? value | ParameterTypeFlags::InOut
1721-
: value - ParameterTypeFlags::InOut);
1710+
return withValueOwnership(isInout ? ValueOwnership::InOut
1711+
: ValueOwnership::Default);
17221712
}
17231713

17241714
ParameterTypeFlags withShared(bool isShared) const {
1725-
return ParameterTypeFlags(isShared ? value | ParameterTypeFlags::Shared
1726-
: value - ParameterTypeFlags::Shared);
1715+
return withValueOwnership(isShared ? ValueOwnership::Shared
1716+
: ValueOwnership::Default);
17271717
}
17281718

17291719
ParameterTypeFlags withOwned(bool isOwned) const {
1730-
return ParameterTypeFlags(isOwned ? value | ParameterTypeFlags::Owned
1731-
: value - ParameterTypeFlags::Owned);
1720+
return withValueOwnership(isOwned ? ValueOwnership::Owned
1721+
: ValueOwnership::Default);
1722+
}
1723+
1724+
ParameterTypeFlags withValueOwnership(ValueOwnership ownership) const {
1725+
return (value - ParameterTypeFlags::Ownership)
1726+
| ParameterFlags(uint8_t(ownership) << OwnershipShift);
17321727
}
17331728

17341729
bool operator ==(const ParameterTypeFlags &other) const {
@@ -1745,9 +1740,8 @@ class ParameterTypeFlags {
17451740
class YieldTypeFlags {
17461741
enum YieldFlags : uint8_t {
17471742
None = 0,
1748-
InOut = 1 << 1,
1749-
Shared = 1 << 2,
1750-
Owned = 1 << 3,
1743+
Ownership = 7,
1744+
OwnershipShift = 0,
17511745

17521746
NumBits = 3
17531747
};
@@ -1764,35 +1758,34 @@ class YieldTypeFlags {
17641758
}
17651759

17661760
YieldTypeFlags(ValueOwnership ownership)
1767-
: value((ownership == ValueOwnership::InOut ? InOut : 0) |
1768-
(ownership == ValueOwnership::Shared ? Shared : 0) |
1769-
(ownership == ValueOwnership::Owned ? Owned : 0)) {}
1761+
: value(uint8_t(ownership) << OwnershipShift) {}
17701762

1771-
bool isInOut() const { return value.contains(InOut); }
1772-
bool isShared() const { return value.contains(Shared); }
1773-
bool isOwned() const { return value.contains(Owned); }
1763+
bool isInOut() const { return getValueOwnership() == ValueOwnership::InOut; }
1764+
bool isShared() const { return getValueOwnership() == ValueOwnership::Shared;}
1765+
bool isOwned() const { return getValueOwnership() == ValueOwnership::Owned; }
17741766

17751767
ValueOwnership getValueOwnership() const {
1776-
if (isInOut())
1777-
return ValueOwnership::InOut;
1778-
else if (isShared())
1779-
return ValueOwnership::Shared;
1780-
else if (isOwned())
1781-
return ValueOwnership::Owned;
1782-
1783-
return ValueOwnership::Default;
1768+
return ValueOwnership((value.toRaw() & Ownership) >> OwnershipShift);
17841769
}
17851770

17861771
YieldTypeFlags withInOut(bool isInout) const {
1787-
return YieldTypeFlags(isInout ? value | InOut : value - InOut);
1772+
return withValueOwnership(isInout ? ValueOwnership::InOut
1773+
: ValueOwnership::Default);
17881774
}
17891775

17901776
YieldTypeFlags withShared(bool isShared) const {
1791-
return YieldTypeFlags(isShared ? value | Shared : value - Shared);
1777+
return withValueOwnership(isShared ? ValueOwnership::Shared
1778+
: ValueOwnership::Default);
17921779
}
17931780

17941781
YieldTypeFlags withOwned(bool isOwned) const {
1795-
return YieldTypeFlags(isOwned ? value | Owned : value - Owned);
1782+
return withValueOwnership(isOwned ? ValueOwnership::Owned
1783+
: ValueOwnership::Default);
1784+
}
1785+
1786+
YieldTypeFlags withValueOwnership(ValueOwnership ownership) const {
1787+
return (value - YieldTypeFlags::Ownership)
1788+
| YieldFlags(uint8_t(ownership) << OwnershipShift);
17961789
}
17971790

17981791
/// Return these flags interpreted as parameter flags.

lib/AST/ASTDumper.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3166,6 +3166,12 @@ namespace {
31663166
printFlag(paramFlags.isVariadic(), "vararg");
31673167
printFlag(paramFlags.isAutoClosure(), "autoclosure");
31683168
printFlag(paramFlags.isEscaping(), "escaping");
3169+
switch (paramFlags.getValueOwnership()) {
3170+
case ValueOwnership::Default: break;
3171+
case ValueOwnership::Owned: printFlag("owned"); break;
3172+
case ValueOwnership::Shared: printFlag("shared"); break;
3173+
case ValueOwnership::InOut: printFlag("inout"); break;
3174+
}
31693175
}
31703176

31713177
public:
@@ -3417,7 +3423,7 @@ namespace {
34173423
if (param.hasLabel())
34183424
printField("name", param.getLabel().str());
34193425
dumpParameterFlags(param.getParameterFlags());
3420-
printRec(param.getOldType());
3426+
printRec(param.getPlainType());
34213427
OS << ")";
34223428
}
34233429
Indent -= 2;

lib/AST/Builtins.cpp

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ getBuiltinGenericFunction(Identifier Id,
196196
SmallVector<ParamDecl*, 4> params;
197197
for (unsigned i = 0, e = ArgParamTypes.size(); i < e; i++) {
198198
auto paramIfaceType = ArgParamTypes[i].getPlainType();
199-
auto specifier = (ArgParamTypes[i].getParameterFlags().isInOut())
200-
? VarDecl::Specifier::InOut
201-
: VarDecl::Specifier::Default;
199+
auto specifier =
200+
VarDecl::getParameterSpecifierForValueOwnership(
201+
ArgParamTypes[i].getParameterFlags().getValueOwnership());
202202
auto PD = new (Context) ParamDecl(specifier,
203203
SourceLoc(), SourceLoc(),
204204
Identifier(), SourceLoc(),
@@ -474,19 +474,13 @@ namespace {
474474
}
475475

476476
template <class G>
477-
void addParameter(const G &generator) {
477+
void addParameter(const G &generator,
478+
ValueOwnership ownership = ValueOwnership::Default) {
478479
Type gTyIface = generator.build(*this);
479-
auto flags = ParameterTypeFlags();
480+
auto flags = ParameterTypeFlags().withValueOwnership(ownership);
480481
InterfaceParams.emplace_back(gTyIface, Identifier(), flags);
481482
}
482483

483-
template <class G>
484-
void addInOutParameter(const G &generator) {
485-
Type gTyIface = generator.build(*this);
486-
auto flags = ParameterTypeFlags().withInOut(true);
487-
InterfaceParams.emplace_back(gTyIface, Identifier(), flags);
488-
}
489-
490484
template <class G>
491485
void setResult(const G &generator) {
492486
InterfaceResult = generator.build(*this);
@@ -591,7 +585,7 @@ static ValueDecl *getLoadOperation(ASTContext &Context, Identifier Id) {
591585

592586
static ValueDecl *getStoreOperation(ASTContext &Context, Identifier Id) {
593587
BuiltinGenericSignatureBuilder builder(Context);
594-
builder.addParameter(makeGenericParam());
588+
builder.addParameter(makeGenericParam(), ValueOwnership::Owned);
595589
builder.addParameter(makeConcrete(Context.TheRawPointerType));
596590
builder.setResult(makeConcrete(TupleType::getEmpty(Context)));
597591
return builder.build(Id);
@@ -633,7 +627,7 @@ static ValueDecl *getIsUniqueOperation(ASTContext &Context, Identifier Id) {
633627
Type Int1Ty = BuiltinIntegerType::get(1, Context);
634628

635629
BuiltinGenericSignatureBuilder builder(Context);
636-
builder.addInOutParameter(makeGenericParam());
630+
builder.addParameter(makeGenericParam(), ValueOwnership::InOut);
637631
builder.setResult(makeConcrete(Int1Ty));
638632
return builder.build(Id);
639633
}
@@ -808,21 +802,35 @@ static ValueDecl *getAtomicStoreOperation(ASTContext &Context, Identifier Id,
808802

809803
static ValueDecl *getNativeObjectCast(ASTContext &Context, Identifier Id,
810804
BuiltinValueKind BV) {
811-
Type BuiltinTy;
812-
if (BV == BuiltinValueKind::BridgeToRawPointer ||
813-
BV == BuiltinValueKind::BridgeFromRawPointer)
814-
BuiltinTy = Context.TheRawPointerType;
815-
else
816-
BuiltinTy = Context.TheNativeObjectType;
805+
806+
ValueOwnership ownership;
807+
Type builtinTy;
808+
switch (BV) {
809+
case BuiltinValueKind::CastToNativeObject:
810+
case BuiltinValueKind::UnsafeCastToNativeObject:
811+
case BuiltinValueKind::CastFromNativeObject:
812+
builtinTy = Context.TheNativeObjectType;
813+
ownership = ValueOwnership::Owned;
814+
break;
815+
816+
case BuiltinValueKind::BridgeToRawPointer:
817+
case BuiltinValueKind::BridgeFromRawPointer:
818+
builtinTy = Context.TheRawPointerType;
819+
ownership = ValueOwnership::Default;
820+
break;
821+
822+
default:
823+
llvm_unreachable("unexpected kind");
824+
}
817825

818826
BuiltinGenericSignatureBuilder builder(Context);
819827
if (BV == BuiltinValueKind::CastToNativeObject ||
820828
BV == BuiltinValueKind::UnsafeCastToNativeObject ||
821829
BV == BuiltinValueKind::BridgeToRawPointer) {
822-
builder.addParameter(makeGenericParam());
823-
builder.setResult(makeConcrete(BuiltinTy));
830+
builder.addParameter(makeGenericParam(), ownership);
831+
builder.setResult(makeConcrete(builtinTy));
824832
} else {
825-
builder.addParameter(makeConcrete(BuiltinTy));
833+
builder.addParameter(makeConcrete(builtinTy), ownership);
826834
builder.setResult(makeGenericParam());
827835
}
828836
return builder.build(Id);
@@ -833,7 +841,7 @@ static ValueDecl *getCastToBridgeObjectOperation(ASTContext &C,
833841
auto wordType = BuiltinIntegerType::get(BuiltinIntegerWidth::pointer(),
834842
C);
835843
BuiltinGenericSignatureBuilder builder(C);
836-
builder.addParameter(makeGenericParam());
844+
builder.addParameter(makeGenericParam(), ValueOwnership::Owned);
837845
builder.addParameter(makeConcrete(wordType));
838846
builder.setResult(makeConcrete(C.TheBridgeObjectType));
839847
return builder.build(Id);
@@ -846,7 +854,7 @@ static ValueDecl *getCastFromBridgeObjectOperation(ASTContext &C,
846854
switch (BV) {
847855
case BuiltinValueKind::CastReferenceFromBridgeObject: {
848856
BuiltinGenericSignatureBuilder builder(C);
849-
builder.addParameter(makeConcrete(BridgeTy));
857+
builder.addParameter(makeConcrete(BridgeTy), ValueOwnership::Owned);
850858
builder.setResult(makeGenericParam());
851859
return builder.build(Id);
852860
}
@@ -906,7 +914,7 @@ static ValueDecl *getCastReferenceOperation(ASTContext &ctx,
906914
// <T, U> T -> U
907915
// SILGen and IRGen check additional constraints during lowering.
908916
BuiltinGenericSignatureBuilder builder(ctx, 2);
909-
builder.addParameter(makeGenericParam(0));
917+
builder.addParameter(makeGenericParam(0), ValueOwnership::Owned);
910918
builder.setResult(makeGenericParam(1));
911919
return builder.build(name);
912920
}
@@ -916,7 +924,7 @@ static ValueDecl *getReinterpretCastOperation(ASTContext &ctx,
916924
// <T, U> T -> U
917925
// SILGen and IRGen check additional constraints during lowering.
918926
BuiltinGenericSignatureBuilder builder(ctx, 2);
919-
builder.addParameter(makeGenericParam(0));
927+
builder.addParameter(makeGenericParam(0), ValueOwnership::Owned);
920928
builder.setResult(makeGenericParam(1));
921929
return builder.build(name);
922930
}
@@ -949,7 +957,7 @@ static ValueDecl *getTSanInoutAccess(ASTContext &Context, Identifier Id) {
949957
static ValueDecl *getAddressOfOperation(ASTContext &Context, Identifier Id) {
950958
// <T> (@inout T) -> RawPointer
951959
BuiltinGenericSignatureBuilder builder(Context);
952-
builder.addInOutParameter(makeGenericParam());
960+
builder.addParameter(makeGenericParam(), ValueOwnership::InOut);
953961
builder.setResult(makeConcrete(Context.TheRawPointerType));
954962
return builder.build(Id);
955963
}
@@ -976,7 +984,7 @@ static ValueDecl *getTypeJoinInoutOperation(ASTContext &Context,
976984
Identifier Id) {
977985
// <T,U,V> (inout T, U.Type) -> V.Type
978986
BuiltinGenericSignatureBuilder builder(Context, 3);
979-
builder.addInOutParameter(makeGenericParam(0));
987+
builder.addParameter(makeGenericParam(0), ValueOwnership::InOut);
980988
builder.addParameter(makeMetatype(makeGenericParam(1)));
981989
builder.setResult(makeMetatype(makeGenericParam(2)));
982990
return builder.build(Id);

lib/RemoteAST/RemoteAST.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,7 @@ class RemoteASTTypeBuilder {
364364
auto flags = param.getFlags();
365365
auto ownership = flags.getValueOwnership();
366366
auto parameterFlags = ParameterTypeFlags()
367-
.withInOut(ownership == ValueOwnership::InOut)
368-
.withShared(ownership == ValueOwnership::Shared)
369-
.withOwned(ownership == ValueOwnership::Owned)
367+
.withValueOwnership(ownership)
370368
.withVariadic(flags.isVariadic());
371369

372370
funcParams.push_back(AnyFunctionType::Param(type, label, parameterFlags));

lib/SILGen/SILGenBuiltin.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,16 @@
3030
using namespace swift;
3131
using namespace Lowering;
3232

33+
static bool isTrivialShuffle(TupleShuffleExpr *shuffle) {
34+
// Each element must be mapped to the corresponding element of the input.
35+
auto mapping = shuffle->getElementMapping();
36+
for (auto index : indices(mapping)) {
37+
if (mapping[index] < 0 || unsigned(mapping[index]) != index)
38+
return false;
39+
}
40+
return true;
41+
}
42+
3343
/// Break down an expression that's the formal argument expression to
3444
/// a builtin function, returning its individualized arguments.
3545
///
@@ -43,7 +53,15 @@ static ArrayRef<Expr*> decomposeArguments(SILGenFunction &SGF,
4353
assert(arg->getType()->castTo<TupleType>()->getNumElements()
4454
== expectedCount);
4555

46-
auto tuple = dyn_cast<TupleExpr>(arg->getSemanticsProvidingExpr());
56+
// The use of owned parameters can trip up CSApply enough to introduce
57+
// a trivial tuple shuffle here.
58+
arg = arg->getSemanticsProvidingExpr();
59+
if (auto shuffle = dyn_cast<TupleShuffleExpr>(arg)) {
60+
if (isTrivialShuffle(shuffle))
61+
arg = shuffle->getSubExpr();
62+
}
63+
64+
auto tuple = dyn_cast<TupleExpr>(arg);
4765
if (tuple && tuple->getElements().size() == expectedCount) {
4866
return tuple->getElements();
4967
}

0 commit comments

Comments
 (0)