Skip to content

Commit c6c9427

Browse files
committed
Add a new parameter convention @in_cxx for non-trivial C++ classes
that are passed indirectly and destructed by the caller Fix a bug where `@in`, which indicates the callee is responsible for destroying the passed object, was being used to pass such classes. rdar://122707697
1 parent ed45c9c commit c6c9427

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+674
-56
lines changed

SwiftCompilerSources/Sources/SIL/Argument.swift

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ public enum ArgumentConvention : CustomStringConvertible {
347347
/// convention used by mutable captures in @noescape closures.
348348
case indirectInoutAliasable
349349

350+
/// This argument is passed indirectly, i.e. by directly passing the address
351+
/// of an object in memory. The callee may modify, but does not destroy the
352+
/// object.
353+
case indirectInCXX
354+
350355
/// This argument represents an indirect return value address. The callee stores
351356
/// the returned value to this argument. At the time when the function is called,
352357
/// the memory location referenced by the argument is uninitialized.
@@ -402,8 +407,9 @@ public enum ArgumentConvention : CustomStringConvertible {
402407
public var isIndirect: Bool {
403408
switch self {
404409
case .indirectIn, .indirectInGuaranteed,
405-
.indirectInout, .indirectInoutAliasable, .indirectOut,
406-
.packOut, .packInout, .packOwned, .packGuaranteed:
410+
.indirectInout, .indirectInoutAliasable, .indirectInCXX,
411+
.indirectOut, .packOut, .packInout, .packOwned,
412+
.packGuaranteed:
407413
return true
408414
case .directOwned, .directUnowned, .directGuaranteed:
409415
return false
@@ -416,7 +422,8 @@ public enum ArgumentConvention : CustomStringConvertible {
416422
.packOwned, .packGuaranteed:
417423
return true
418424
case .directOwned, .directUnowned, .directGuaranteed,
419-
.indirectInout, .indirectInoutAliasable, .indirectOut,
425+
.indirectInout, .indirectInoutAliasable, .indirectInCXX,
426+
.indirectOut,
420427
.packOut, .packInout:
421428
return false
422429
}
@@ -428,7 +435,7 @@ public enum ArgumentConvention : CustomStringConvertible {
428435
return true
429436
case .indirectInGuaranteed, .directGuaranteed, .packGuaranteed,
430437
.indirectIn, .directOwned, .directUnowned,
431-
.indirectInout, .indirectInoutAliasable,
438+
.indirectInout, .indirectInoutAliasable, .indirectInCXX,
432439
.packInout, .packOwned:
433440
return false
434441
}
@@ -439,8 +446,8 @@ public enum ArgumentConvention : CustomStringConvertible {
439446
case .indirectInGuaranteed, .directGuaranteed, .packGuaranteed:
440447
return true
441448
case .indirectIn, .directOwned, .directUnowned,
442-
.indirectInout, .indirectInoutAliasable, .indirectOut,
443-
.packOut, .packInout, .packOwned:
449+
.indirectInout, .indirectInoutAliasable, .indirectInCXX,
450+
.indirectOut, .packOut, .packInout, .packOwned:
444451
return false
445452
}
446453
}
@@ -451,6 +458,7 @@ public enum ArgumentConvention : CustomStringConvertible {
451458
.indirectOut,
452459
.indirectInGuaranteed,
453460
.indirectInout,
461+
.indirectInCXX,
454462
.packOut,
455463
.packInout,
456464
.packOwned,
@@ -475,6 +483,7 @@ public enum ArgumentConvention : CustomStringConvertible {
475483
case .indirectIn,
476484
.indirectOut,
477485
.indirectInGuaranteed,
486+
.indirectInCXX,
478487
.directUnowned,
479488
.directGuaranteed,
480489
.directOwned,
@@ -495,6 +504,8 @@ public enum ArgumentConvention : CustomStringConvertible {
495504
return "indirectInout"
496505
case .indirectInoutAliasable:
497506
return "indirectInoutAliasable"
507+
case .indirectInCXX:
508+
return "indirectInCXX"
498509
case .indirectOut:
499510
return "indirectOut"
500511
case .directOwned:
@@ -529,6 +540,7 @@ extension BridgedArgumentConvention {
529540
case .Indirect_In_Guaranteed: return .indirectInGuaranteed
530541
case .Indirect_Inout: return .indirectInout
531542
case .Indirect_InoutAliasable: return .indirectInoutAliasable
543+
case .Indirect_In_CXX: return .indirectInCXX
532544
case .Indirect_Out: return .indirectOut
533545
case .Direct_Owned: return .directOwned
534546
case .Direct_Unowned: return .directUnowned
@@ -550,6 +562,7 @@ extension ArgumentConvention {
550562
case .indirectInGuaranteed: return .Indirect_In_Guaranteed
551563
case .indirectInout: return .Indirect_Inout
552564
case .indirectInoutAliasable: return .Indirect_InoutAliasable
565+
case .indirectInCXX: return .Indirect_In_CXX
553566
case .indirectOut: return .Indirect_Out
554567
case .directOwned: return .Direct_Owned
555568
case .directUnowned: return .Direct_Unowned

SwiftCompilerSources/Sources/SIL/Effects.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ public struct SideEffects : CustomStringConvertible, NoReflectionChildren {
561561
result.memory = SideEffects.Memory()
562562
}
563563

564-
case .indirectInout, .indirectInoutAliasable:
564+
case .indirectInout, .indirectInoutAliasable, .indirectInCXX:
565565
break
566566
}
567567
return result

SwiftCompilerSources/Sources/SIL/FunctionConvention.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ public struct ParameterInfo : CustomStringConvertible {
164164
switch convention {
165165
case .indirectIn, .indirectInGuaranteed:
166166
return hasLoweredAddresses || type.isOpenedExistentialWithError()
167-
case .indirectInout, .indirectInoutAliasable:
167+
case .indirectInout, .indirectInoutAliasable, .indirectInCXX:
168168
return true
169169
case .directOwned, .directUnowned, .directGuaranteed:
170170
return false

include/swift/AST/Types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4059,6 +4059,11 @@ enum class ParameterConvention : uint8_t {
40594059
/// convention used by mutable captures in @noescape closures.
40604060
Indirect_InoutAliasable,
40614061

4062+
/// This argument is passed indirectly, i.e. by directly passing the address
4063+
/// of an object in memory. The callee may modify, but does not destroy the
4064+
/// object.
4065+
Indirect_In_CXX,
4066+
40624067
/// This argument is passed directly. Its type is non-trivial, and the callee
40634068
/// is responsible for destroying it.
40644069
Direct_Owned,
@@ -4099,6 +4104,7 @@ inline bool isIndirectFormalParameter(ParameterConvention conv) {
40994104
case ParameterConvention::Indirect_In:
41004105
case ParameterConvention::Indirect_Inout:
41014106
case ParameterConvention::Indirect_InoutAliasable:
4107+
case ParameterConvention::Indirect_In_CXX:
41024108
case ParameterConvention::Indirect_In_Guaranteed:
41034109
return true;
41044110

@@ -4121,6 +4127,7 @@ inline bool isConsumedParameter(ParameterConvention conv) {
41214127

41224128
case ParameterConvention::Indirect_Inout:
41234129
case ParameterConvention::Indirect_InoutAliasable:
4130+
case ParameterConvention::Indirect_In_CXX:
41244131
case ParameterConvention::Direct_Unowned:
41254132
case ParameterConvention::Direct_Guaranteed:
41264133
case ParameterConvention::Indirect_In_Guaranteed:
@@ -4143,6 +4150,7 @@ inline bool isGuaranteedParameter(ParameterConvention conv) {
41434150

41444151
case ParameterConvention::Indirect_Inout:
41454152
case ParameterConvention::Indirect_InoutAliasable:
4153+
case ParameterConvention::Indirect_In_CXX:
41464154
case ParameterConvention::Indirect_In:
41474155
case ParameterConvention::Direct_Unowned:
41484156
case ParameterConvention::Direct_Owned:
@@ -4157,6 +4165,7 @@ inline bool isMutatingParameter(ParameterConvention conv) {
41574165
switch (conv) {
41584166
case ParameterConvention::Indirect_Inout:
41594167
case ParameterConvention::Indirect_InoutAliasable:
4168+
case ParameterConvention::Indirect_In_CXX:
41604169
case ParameterConvention::Pack_Inout:
41614170
return true;
41624171

@@ -4183,6 +4192,7 @@ inline bool isPackParameter(ParameterConvention conv) {
41834192
case ParameterConvention::Indirect_In_Guaranteed:
41844193
case ParameterConvention::Indirect_Inout:
41854194
case ParameterConvention::Indirect_InoutAliasable:
4195+
case ParameterConvention::Indirect_In_CXX:
41864196
case ParameterConvention::Indirect_In:
41874197
case ParameterConvention::Direct_Guaranteed:
41884198
case ParameterConvention::Direct_Unowned:

include/swift/SIL/ApplySite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ class ApplySite {
412412
: SILArgumentConvention::Direct_Owned;
413413
case SILArgumentConvention::Indirect_In:
414414
case SILArgumentConvention::Indirect_In_Guaranteed:
415+
case SILArgumentConvention::Indirect_In_CXX:
415416
return pai->isOnStack() ? SILArgumentConvention::Indirect_In_Guaranteed
416417
: SILArgumentConvention::Indirect_In;
417418
case SILArgumentConvention::Pack_Guaranteed:

include/swift/SIL/SILArgumentConvention.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct SILArgumentConvention {
2828
Indirect_In_Guaranteed,
2929
Indirect_Inout,
3030
Indirect_InoutAliasable,
31+
Indirect_In_CXX,
3132
Indirect_Out,
3233
Direct_Owned,
3334
Direct_Unowned,
@@ -55,6 +56,9 @@ struct SILArgumentConvention {
5556
case ParameterConvention::Indirect_In_Guaranteed:
5657
Value = SILArgumentConvention::Indirect_In_Guaranteed;
5758
return;
59+
case ParameterConvention::Indirect_In_CXX:
60+
Value = SILArgumentConvention::Indirect_In_CXX;
61+
return;
5862
case ParameterConvention::Direct_Unowned:
5963
Value = SILArgumentConvention::Direct_Unowned;
6064
return;
@@ -92,6 +96,7 @@ struct SILArgumentConvention {
9296
case SILArgumentConvention::Indirect_In_Guaranteed:
9397
case SILArgumentConvention::Indirect_In:
9498
case SILArgumentConvention::Indirect_Out:
99+
case SILArgumentConvention::Indirect_In_CXX:
95100
case SILArgumentConvention::Direct_Unowned:
96101
case SILArgumentConvention::Direct_Owned:
97102
case SILArgumentConvention::Direct_Guaranteed:
@@ -114,6 +119,7 @@ struct SILArgumentConvention {
114119
case SILArgumentConvention::Indirect_Inout:
115120
case SILArgumentConvention::Indirect_Out:
116121
case SILArgumentConvention::Indirect_InoutAliasable:
122+
case SILArgumentConvention::Indirect_In_CXX:
117123
case SILArgumentConvention::Direct_Unowned:
118124
case SILArgumentConvention::Pack_Inout:
119125
case SILArgumentConvention::Pack_Guaranteed:
@@ -133,6 +139,7 @@ struct SILArgumentConvention {
133139
case SILArgumentConvention::Indirect_In:
134140
case SILArgumentConvention::Indirect_Out:
135141
case SILArgumentConvention::Indirect_InoutAliasable:
142+
case SILArgumentConvention::Indirect_In_CXX:
136143
case SILArgumentConvention::Direct_Unowned:
137144
case SILArgumentConvention::Direct_Owned:
138145
case SILArgumentConvention::Pack_Inout:
@@ -150,6 +157,7 @@ struct SILArgumentConvention {
150157
case SILArgumentConvention::Indirect_Out:
151158
case SILArgumentConvention::Indirect_In_Guaranteed:
152159
case SILArgumentConvention::Indirect_Inout:
160+
case SILArgumentConvention::Indirect_In_CXX:
153161
return true;
154162

155163
case SILArgumentConvention::Indirect_InoutAliasable:
@@ -176,6 +184,7 @@ struct SILArgumentConvention {
176184
case SILArgumentConvention::Indirect_In_Guaranteed:
177185
case SILArgumentConvention::Indirect_Inout:
178186
case SILArgumentConvention::Indirect_InoutAliasable:
187+
case SILArgumentConvention::Indirect_In_CXX:
179188
case SILArgumentConvention::Direct_Unowned:
180189
case SILArgumentConvention::Direct_Guaranteed:
181190
case SILArgumentConvention::Direct_Owned:

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ enum class BridgedArgumentConvention {
136136
Indirect_In_Guaranteed,
137137
Indirect_Inout,
138138
Indirect_InoutAliasable,
139+
Indirect_In_CXX,
139140
Indirect_Out,
140141
Direct_Owned,
141142
Direct_Unowned,
@@ -167,6 +168,7 @@ struct BridgedParameterInfo {
167168
case BridgedArgumentConvention::Indirect_In_Guaranteed: return swift::ParameterConvention::Indirect_In_Guaranteed;
168169
case BridgedArgumentConvention::Indirect_Inout: return swift::ParameterConvention::Indirect_Inout;
169170
case BridgedArgumentConvention::Indirect_InoutAliasable: return swift::ParameterConvention::Indirect_InoutAliasable;
171+
case BridgedArgumentConvention::Indirect_In_CXX: return swift::ParameterConvention::Indirect_In_CXX;
170172
case BridgedArgumentConvention::Indirect_Out: break;
171173
case BridgedArgumentConvention::Direct_Owned: return swift::ParameterConvention::Direct_Owned;
172174
case BridgedArgumentConvention::Direct_Unowned: return swift::ParameterConvention::Direct_Unowned;

include/swift/SIL/SILDeclRef.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ struct SILDeclRef {
200200
/// Set if this is for an async let closure.
201201
unsigned isAsyncLetClosure : 1;
202202

203+
unsigned CFunctionPointer : 1;
204+
203205
PointerUnion<AutoDiffDerivativeFunctionIdentifier *,
204206
const GenericSignatureImpl *, CustomAttr *>
205207
pointer;
@@ -234,7 +236,7 @@ struct SILDeclRef {
234236
: loc(), kind(Kind::Func), isForeign(0), isDistributed(0),
235237
isKnownToBeLocal(0), isRuntimeAccessible(0),
236238
backDeploymentKind(BackDeploymentKind::None), defaultArgIndex(0),
237-
isAsyncLetClosure(0) {}
239+
isAsyncLetClosure(0), CFunctionPointer(0) {}
238240

239241
/// Produces a SILDeclRef of the given kind for the given decl.
240242
explicit SILDeclRef(
@@ -257,11 +259,10 @@ struct SILDeclRef {
257259
/// for the containing ClassDecl.
258260
/// - If 'loc' is a global VarDecl, this returns its GlobalAccessor
259261
/// SILDeclRef.
260-
explicit SILDeclRef(
261-
Loc loc,
262-
bool isForeign = false,
263-
bool isDistributed = false,
264-
bool isDistributedLocal = false);
262+
explicit SILDeclRef(Loc loc, bool isForeign = false,
263+
bool isDistributed = false,
264+
bool isDistributedLocal = false,
265+
bool isCFunctionPointer = false);
265266

266267
/// See above put produces a prespecialization according to the signature.
267268
explicit SILDeclRef(Loc loc, GenericSignature prespecializationSig);
@@ -290,6 +291,8 @@ struct SILDeclRef {
290291
bool hasAutoClosureExpr() const;
291292
bool hasFuncDecl() const;
292293

294+
bool hasCFunctionPointer() const { return CFunctionPointer; }
295+
293296
ValueDecl *getDecl() const { return loc.dyn_cast<ValueDecl *>(); }
294297
AbstractClosureExpr *getAbstractClosureExpr() const {
295298
return loc.dyn_cast<AbstractClosureExpr *>();

include/swift/SIL/SILFunctionConventions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ inline bool SILModuleConventions::isIndirectSILParam(SILParameterInfo param,
592592

593593
case ParameterConvention::Indirect_In:
594594
case ParameterConvention::Indirect_In_Guaranteed:
595+
case ParameterConvention::Indirect_In_CXX:
595596
return isTypeIndirectForIndirectParamConvention(param.getInterfaceType(),
596597
loweredAddresses);
597598
case ParameterConvention::Indirect_Inout:

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,7 @@ static char getParamConvention(ParameterConvention conv) {
11361136
case ParameterConvention::Indirect_Inout: return 'l';
11371137
case ParameterConvention::Indirect_InoutAliasable: return 'b';
11381138
case ParameterConvention::Indirect_In_Guaranteed: return 'n';
1139+
case ParameterConvention::Indirect_In_CXX: return 'C';
11391140
case ParameterConvention::Direct_Owned: return 'x';
11401141
case ParameterConvention::Direct_Unowned: return 'y';
11411142
case ParameterConvention::Direct_Guaranteed: return 'g';

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6731,6 +6731,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
67316731
case ParameterConvention::Indirect_In:
67326732
case ParameterConvention::Indirect_Inout:
67336733
case ParameterConvention::Indirect_InoutAliasable:
6734+
case ParameterConvention::Indirect_In_CXX:
67346735
case ParameterConvention::Indirect_In_Guaranteed:
67356736
llvm_unreachable("callee convention cannot be indirect");
67366737
case ParameterConvention::Pack_Guaranteed:
@@ -7500,6 +7501,7 @@ StringRef swift::getStringForParameterConvention(ParameterConvention conv) {
75007501
case ParameterConvention::Indirect_In_Guaranteed: return "@in_guaranteed ";
75017502
case ParameterConvention::Indirect_Inout: return "@inout ";
75027503
case ParameterConvention::Indirect_InoutAliasable: return "@inout_aliasable ";
7504+
case ParameterConvention::Indirect_In_CXX: return "@in_cxx ";
75037505
case ParameterConvention::Direct_Owned: return "@owned ";
75047506
case ParameterConvention::Direct_Unowned: return "";
75057507
case ParameterConvention::Direct_Guaranteed: return "@guaranteed ";

lib/Demangling/Demangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,6 +2160,7 @@ NodePointer Demangler::demangleImplParamConvention(Node::Kind ConvKind) {
21602160
case 'l': attr = "@inout"; break;
21612161
case 'b': attr = "@inout_aliasable"; break;
21622162
case 'n': attr = "@in_guaranteed"; break;
2163+
case 'C': attr = "@in_cxx"; break;
21632164
case 'x': attr = "@owned"; break;
21642165
case 'g': attr = "@guaranteed"; break;
21652166
case 'e': attr = "@deallocating"; break;

lib/Demangling/Remangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,6 +2109,7 @@ ManglingError Remangler::mangleImplFunctionType(Node *node, unsigned depth) {
21092109
.Case("@inout", 'l')
21102110
.Case("@inout_aliasable", 'b')
21112111
.Case("@in_guaranteed", 'n')
2112+
.Case("@in_cxx", 'C')
21122113
.Case("@in_constant", 'c')
21132114
.Case("@owned", 'x')
21142115
.Case("@guaranteed", 'g')

lib/IRGen/GenCall.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,6 +1638,7 @@ const TypeInfo &SignatureExpansion::expand(SILParameterInfo param) {
16381638
switch (auto conv = param.getConvention()) {
16391639
case ParameterConvention::Indirect_In:
16401640
case ParameterConvention::Indirect_In_Guaranteed:
1641+
case ParameterConvention::Indirect_In_CXX:
16411642
addIndirectValueParameterAttributes(IGM, Attrs, ti, ParamIRTypes.size());
16421643
addPointerParameter(IGM.getStorageType(getSILFuncConventions().getSILType(
16431644
param, IGM.getMaximalTypeExpansionContext())));

lib/IRGen/GenDistributed.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
544544
break;
545545
}
546546

547+
case ParameterConvention::Indirect_In_CXX:
547548
case ParameterConvention::Indirect_In_Guaranteed: {
548549
// The argument is +0, so we can use the address of the param in
549550
// the context directly.

lib/IRGen/GenFunc.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,7 @@ CanType irgen::getArgumentLoweringType(CanType type, SILParameterInfo paramInfo,
846846
// address.
847847
case ParameterConvention::Indirect_In:
848848
case ParameterConvention::Indirect_In_Guaranteed:
849+
case ParameterConvention::Indirect_In_CXX:
849850
if (isNoEscape)
850851
return CanInOutType::get(type);
851852
else
@@ -1508,6 +1509,7 @@ static llvm::Value *emitPartialApplicationForwarder(
15081509
break;
15091510
case ParameterConvention::Indirect_Inout:
15101511
case ParameterConvention::Indirect_InoutAliasable:
1512+
case ParameterConvention::Indirect_In_CXX:
15111513
case ParameterConvention::Indirect_In:
15121514
case ParameterConvention::Indirect_In_Guaranteed:
15131515
case ParameterConvention::Pack_Guaranteed:
@@ -1625,6 +1627,7 @@ static llvm::Value *emitPartialApplicationForwarder(
16251627
break;
16261628

16271629
case ParameterConvention::Indirect_In_Guaranteed:
1630+
case ParameterConvention::Indirect_In_CXX:
16281631
case ParameterConvention::Direct_Guaranteed:
16291632
dependsOnContextLifetime = true;
16301633
if (outType->getCalleeConvention() ==
@@ -1750,6 +1753,7 @@ static llvm::Value *emitPartialApplicationForwarder(
17501753
}
17511754
break;
17521755
}
1756+
case ParameterConvention::Indirect_In_CXX:
17531757
case ParameterConvention::Indirect_In_Guaranteed:
17541758
if (outType->isNoEscape()) {
17551759
cast<LoadableTypeInfo>(fieldTI).loadAsCopy(subIGF, fieldAddr, param);
@@ -2301,6 +2305,7 @@ std::optional<StackAddress> irgen::emitFunctionPartialApplication(
23012305
switch (argConventions[i]) {
23022306
// Take indirect value arguments out of memory.
23032307
case ParameterConvention::Indirect_In:
2308+
case ParameterConvention::Indirect_In_CXX:
23042309
case ParameterConvention::Indirect_In_Guaranteed: {
23052310
if (outType->isNoEscape()) {
23062311
cast<LoadableTypeInfo>(fieldLayout.getType())

0 commit comments

Comments
 (0)