Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a new parameter convention @in_cxx for non-trivial C++ classes that are passed indirectly and destructed by the caller #73019

Merged
merged 10 commits into from
Jun 27, 2024
Next Next commit
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
  • Loading branch information
ahatanaka committed Jun 26, 2024
commit e86a0a0bfeb51d27afaad962b7db54785f5e4afc
28 changes: 21 additions & 7 deletions SwiftCompilerSources/Sources/SIL/Argument.swift
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,12 @@ public enum ArgumentConvention : CustomStringConvertible {
/// convention used by mutable captures in @noescape closures.
case indirectInoutAliasable

/// This argument is passed indirectly, i.e. by directly passing the address
/// of an object in memory. The callee may modify, but does not destroy the
/// object. This corresponds to the parameter-passing convention of the
/// Itanium C++ ABI, which is used ubiquitously on non-Windows targets.
case indirectInCXX

/// This argument represents an indirect return value address. The callee stores
/// the returned value to this argument. At the time when the function is called,
/// the memory location referenced by the argument is uninitialized.
Expand Down Expand Up @@ -407,8 +413,9 @@ public enum ArgumentConvention : CustomStringConvertible {
public var isIndirect: Bool {
switch self {
case .indirectIn, .indirectInGuaranteed,
.indirectInout, .indirectInoutAliasable, .indirectOut,
.packOut, .packInout, .packOwned, .packGuaranteed:
.indirectInout, .indirectInoutAliasable, .indirectInCXX,
.indirectOut, .packOut, .packInout, .packOwned,
.packGuaranteed:
return true
case .directOwned, .directUnowned, .directGuaranteed:
return false
Expand All @@ -417,11 +424,12 @@ public enum ArgumentConvention : CustomStringConvertible {

public var isIndirectIn: Bool {
switch self {
case .indirectIn, .indirectInGuaranteed,
case .indirectIn, .indirectInGuaranteed, .indirectInCXX,
.packOwned, .packGuaranteed:
return true
case .directOwned, .directUnowned, .directGuaranteed,
.indirectInout, .indirectInoutAliasable, .indirectOut,
.indirectInout, .indirectInoutAliasable,
.indirectOut,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what this property is used for, but if it includes both @in and @in_guaranteed, it probably ought to include @in_cxx.

.packOut, .packInout:
return false
}
Expand All @@ -433,7 +441,7 @@ public enum ArgumentConvention : CustomStringConvertible {
return true
case .indirectInGuaranteed, .directGuaranteed, .packGuaranteed,
.indirectIn, .directOwned, .directUnowned,
.indirectInout, .indirectInoutAliasable,
.indirectInout, .indirectInoutAliasable, .indirectInCXX,
.packInout, .packOwned:
return false
}
Expand All @@ -444,8 +452,8 @@ public enum ArgumentConvention : CustomStringConvertible {
case .indirectInGuaranteed, .directGuaranteed, .packGuaranteed:
return true
case .indirectIn, .directOwned, .directUnowned,
.indirectInout, .indirectInoutAliasable, .indirectOut,
.packOut, .packInout, .packOwned:
.indirectInout, .indirectInoutAliasable, .indirectInCXX,
.indirectOut, .packOut, .packInout, .packOwned:
return false
}
}
Expand All @@ -467,6 +475,7 @@ public enum ArgumentConvention : CustomStringConvertible {
.indirectOut,
.indirectInGuaranteed,
.indirectInout,
.indirectInCXX,
.packOut,
.packInout,
.packOwned,
Expand All @@ -491,6 +500,7 @@ public enum ArgumentConvention : CustomStringConvertible {
case .indirectIn,
.indirectOut,
.indirectInGuaranteed,
.indirectInCXX,
.directUnowned,
.directGuaranteed,
.directOwned,
Expand All @@ -511,6 +521,8 @@ public enum ArgumentConvention : CustomStringConvertible {
return "indirectInout"
case .indirectInoutAliasable:
return "indirectInoutAliasable"
case .indirectInCXX:
return "indirectInCXX"
case .indirectOut:
return "indirectOut"
case .directOwned:
Expand Down Expand Up @@ -545,6 +557,7 @@ extension BridgedArgumentConvention {
case .Indirect_In_Guaranteed: return .indirectInGuaranteed
case .Indirect_Inout: return .indirectInout
case .Indirect_InoutAliasable: return .indirectInoutAliasable
case .Indirect_In_CXX: return .indirectInCXX
case .Indirect_Out: return .indirectOut
case .Direct_Owned: return .directOwned
case .Direct_Unowned: return .directUnowned
Expand All @@ -566,6 +579,7 @@ extension ArgumentConvention {
case .indirectInGuaranteed: return .Indirect_In_Guaranteed
case .indirectInout: return .Indirect_Inout
case .indirectInoutAliasable: return .Indirect_InoutAliasable
case .indirectInCXX: return .Indirect_In_CXX
case .indirectOut: return .Indirect_Out
case .directOwned: return .Direct_Owned
case .directUnowned: return .Direct_Unowned
Expand Down
2 changes: 1 addition & 1 deletion SwiftCompilerSources/Sources/SIL/Effects.swift
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ public struct SideEffects : CustomStringConvertible, NoReflectionChildren {
result.memory = SideEffects.Memory()
}

case .indirectInout, .indirectInoutAliasable:
case .indirectInout, .indirectInoutAliasable, .indirectInCXX:
break
}
return result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public struct ParameterInfo : CustomStringConvertible {
switch convention {
case .indirectIn, .indirectInGuaranteed:
return hasLoweredAddresses || type.isOpenedExistentialWithError()
case .indirectInout, .indirectInoutAliasable:
case .indirectInout, .indirectInoutAliasable, .indirectInCXX:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like @gottesmm to weigh in here. Naively, I'd say it'd be nice to model these as direct arguments in non-lowered-addresses mode, but the fact that we have to destroy the value in the caller (and observe any mutations made by the callee) might make that impractical.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @atrick

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's potentially useful to have a SIL convention that says: the caller and callee must observe the same address of an addressable value. But that isn't generally implementable for all T given reabstraction of function types and tuples.

I'm still baffled by what this convention means. The comment says it's about observing mutation. If that's true, then we should pass a SIL address in non-lowered-addresses mode. But why, then aren't you using inout?

If it is not the case that the caller and callee need to observe the same address, then we should pass SIL values instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw an assertion failure when I tried using inout by making getIndirectCParameterConvention return Indirect_Inout instead of Indirect_In_CXX.

The failed assertion is in ArgEmitter::emit:

assert(arg.hasLValueType() == param.isIndirectInOut());

Copy link
Contributor

@rjmccall rjmccall Apr 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the Itanium C++ ABI convention in which non-trivial C++ values are passed indirectly but the caller is responsible for destroying them. The caller and callee do need to observe the same address. It is essentially the same as inout at the SIL level except that it's not inout in the source language, and I didn't want us to have to weaken all the SIL lowering assertions that e.g. an inout parameter always corresponds to an l-value argument expression, because those are quite useful in catching type-checking bugs. That is why I suggested to Akira that he add a new convention that was mostly treated the same way as inout throughout the SIL pipeline.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably pass SIL arguments to in-cxx by-address at all stages, and make it very clear that the caller can observe mutation.

Can the callee observe aliases?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter object can't be directly named except through the parameter; it's never the same object as e.g. a local variable in the caller. However, it can be aliased in the same way that almost any C++ object technically can, e.g. by escaping this during construction. We've generally been assuming that that's not something we need to worry about, at least from the perspective of "well, we're obviously not going to be enforce exclusivity on types that don't follow basic local-reasoning principles".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It occurs to me that we probably need special logic when consuming parameters like this. They probably should be consumable as long as the type is movable; we should compile consumption as a C++ move and then enforce use restrictions on the moved-from value just like we would for a Swift value, even though technically the object is still there.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm starting to understand. At the source level, this is pass-by-value into the callee, and the caller has no visibility of that value. But, since the convention requires the caller to destroy the value, the caller's implementation must also observe any mutation.

Just like @in, In ownership SIL (OSSA) the argument should be consumed by the call (not by a separate destroy after the call).

Just like @in, non-address-lowered SIL should pass the value, not an address.

OwnershipModelEliminator could insert a destroy_addr after the call for these arguments. By then, they will be addresses. And IRGen doesn't need to do anything special.

return true
case .directOwned, .directUnowned, .directGuaranteed:
return false
Expand Down
1 change: 1 addition & 0 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,7 @@ mangled in to disambiguate.
PARAM-CONVENTION ::= 'l' // indirect inout
PARAM-CONVENTION ::= 'b' // indirect inout aliasable
PARAM-CONVENTION ::= 'n' // indirect in guaranteed
PARAM-CONVENTION ::= 'C' // indirect in C++
PARAM-CONVENTION ::= 'x' // direct owned
PARAM-CONVENTION ::= 'y' // direct unowned
PARAM-CONVENTION ::= 'g' // direct guaranteed
Expand Down
15 changes: 15 additions & 0 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -4068,6 +4068,12 @@ enum class ParameterConvention : uint8_t {
/// convention used by mutable captures in @noescape closures.
Indirect_InoutAliasable,

/// This argument is passed indirectly, i.e. by directly passing the address
/// of an object in memory. The callee may modify, but does not destroy the
/// object. This corresponds to the parameter-passing convention of the
/// Itanium C++ ABI, which is used ubiquitously on non-Windows targets.
Indirect_In_CXX,

/// This argument is passed directly. Its type is non-trivial, and the callee
/// is responsible for destroying it.
Direct_Owned,
Expand Down Expand Up @@ -4108,6 +4114,7 @@ inline bool isIndirectFormalParameter(ParameterConvention conv) {
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In_Guaranteed:
return true;

Expand All @@ -4126,6 +4133,7 @@ template <bool InCallee>
bool isConsumedParameter(ParameterConvention conv) {
switch (conv) {
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Direct_Owned:
case ParameterConvention::Pack_Owned:
return true;
Expand Down Expand Up @@ -4163,6 +4171,7 @@ bool isGuaranteedParameter(ParameterConvention conv) {

case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In:
case ParameterConvention::Direct_Unowned:
case ParameterConvention::Direct_Owned:
Expand All @@ -4185,6 +4194,7 @@ inline bool isMutatingParameter(ParameterConvention conv) {
switch (conv) {
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Pack_Inout:
return true;

Expand All @@ -4211,6 +4221,7 @@ inline bool isPackParameter(ParameterConvention conv) {
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In:
case ParameterConvention::Direct_Guaranteed:
case ParameterConvention::Direct_Unowned:
Expand Down Expand Up @@ -4291,6 +4302,10 @@ class SILParameterInfo {
return getConvention() == ParameterConvention::Indirect_In;
}

bool isIndirectInCXX() const {
return getConvention() == ParameterConvention::Indirect_In_CXX;
}

bool isIndirectInOut() const {
return getConvention() == ParameterConvention::Indirect_Inout;
}
Expand Down
1 change: 1 addition & 0 deletions include/swift/SIL/ApplySite.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ class ApplySite {
: SILArgumentConvention::Direct_Owned;
case SILArgumentConvention::Indirect_In:
case SILArgumentConvention::Indirect_In_Guaranteed:
case SILArgumentConvention::Indirect_In_CXX:
return pai->isOnStack() ? SILArgumentConvention::Indirect_In_Guaranteed
: SILArgumentConvention::Indirect_In;
case SILArgumentConvention::Pack_Guaranteed:
Expand Down
9 changes: 9 additions & 0 deletions include/swift/SIL/SILArgumentConvention.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct SILArgumentConvention {
Indirect_In_Guaranteed,
Indirect_Inout,
Indirect_InoutAliasable,
Indirect_In_CXX,
Indirect_Out,
Direct_Owned,
Direct_Unowned,
Expand Down Expand Up @@ -55,6 +56,9 @@ struct SILArgumentConvention {
case ParameterConvention::Indirect_In_Guaranteed:
Value = SILArgumentConvention::Indirect_In_Guaranteed;
return;
case ParameterConvention::Indirect_In_CXX:
Value = SILArgumentConvention::Indirect_In_CXX;
return;
case ParameterConvention::Direct_Unowned:
Value = SILArgumentConvention::Direct_Unowned;
return;
Expand Down Expand Up @@ -92,6 +96,7 @@ struct SILArgumentConvention {
case SILArgumentConvention::Indirect_In_Guaranteed:
case SILArgumentConvention::Indirect_In:
case SILArgumentConvention::Indirect_Out:
case SILArgumentConvention::Indirect_In_CXX:
case SILArgumentConvention::Direct_Unowned:
case SILArgumentConvention::Direct_Owned:
case SILArgumentConvention::Direct_Guaranteed:
Expand All @@ -107,6 +112,7 @@ struct SILArgumentConvention {
bool isOwnedConvention() const {
switch (Value) {
case SILArgumentConvention::Indirect_In:
case SILArgumentConvention::Indirect_In_CXX:
case SILArgumentConvention::Direct_Owned:
case SILArgumentConvention::Pack_Owned:
return true;
Expand Down Expand Up @@ -139,6 +145,7 @@ struct SILArgumentConvention {
case SILArgumentConvention::Indirect_In:
case SILArgumentConvention::Indirect_Out:
case SILArgumentConvention::Indirect_InoutAliasable:
case SILArgumentConvention::Indirect_In_CXX:
case SILArgumentConvention::Direct_Unowned:
case SILArgumentConvention::Direct_Owned:
case SILArgumentConvention::Pack_Inout:
Expand All @@ -164,6 +171,7 @@ struct SILArgumentConvention {
case SILArgumentConvention::Indirect_Out:
case SILArgumentConvention::Indirect_In_Guaranteed:
case SILArgumentConvention::Indirect_Inout:
case SILArgumentConvention::Indirect_In_CXX:
return true;

case SILArgumentConvention::Indirect_InoutAliasable:
Expand All @@ -190,6 +198,7 @@ struct SILArgumentConvention {
case SILArgumentConvention::Indirect_In_Guaranteed:
case SILArgumentConvention::Indirect_Inout:
case SILArgumentConvention::Indirect_InoutAliasable:
case SILArgumentConvention::Indirect_In_CXX:
case SILArgumentConvention::Direct_Unowned:
case SILArgumentConvention::Direct_Guaranteed:
case SILArgumentConvention::Direct_Owned:
Expand Down
3 changes: 3 additions & 0 deletions include/swift/SIL/SILBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ enum class BridgedArgumentConvention {
Indirect_In_Guaranteed,
Indirect_Inout,
Indirect_InoutAliasable,
Indirect_In_CXX,
Indirect_Out,
Direct_Owned,
Direct_Unowned,
Expand All @@ -153,6 +154,7 @@ inline swift::ParameterConvention getParameterConvention(BridgedArgumentConventi
case BridgedArgumentConvention::Indirect_In_Guaranteed: return swift::ParameterConvention::Indirect_In_Guaranteed;
case BridgedArgumentConvention::Indirect_Inout: return swift::ParameterConvention::Indirect_Inout;
case BridgedArgumentConvention::Indirect_InoutAliasable: return swift::ParameterConvention::Indirect_InoutAliasable;
case BridgedArgumentConvention::Indirect_In_CXX: return swift::ParameterConvention::Indirect_In_CXX;
case BridgedArgumentConvention::Indirect_Out: break;
case BridgedArgumentConvention::Direct_Owned: return swift::ParameterConvention::Direct_Owned;
case BridgedArgumentConvention::Direct_Unowned: return swift::ParameterConvention::Direct_Unowned;
Expand All @@ -171,6 +173,7 @@ inline BridgedArgumentConvention getArgumentConvention(swift::ParameterConventio
case swift::ParameterConvention::Indirect_In_Guaranteed: return BridgedArgumentConvention::Indirect_In_Guaranteed;
case swift::ParameterConvention::Indirect_Inout: return BridgedArgumentConvention::Indirect_Inout;
case swift::ParameterConvention::Indirect_InoutAliasable: return BridgedArgumentConvention::Indirect_InoutAliasable;
case swift::ParameterConvention::Indirect_In_CXX: return BridgedArgumentConvention::Indirect_In_CXX;
case swift::ParameterConvention::Direct_Owned: return BridgedArgumentConvention::Direct_Owned;
case swift::ParameterConvention::Direct_Unowned: return BridgedArgumentConvention::Direct_Unowned;
case swift::ParameterConvention::Direct_Guaranteed: return BridgedArgumentConvention::Direct_Guaranteed;
Expand Down
1 change: 1 addition & 0 deletions include/swift/SIL/SILFunctionConventions.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,7 @@ inline bool SILModuleConventions::isIndirectSILParam(SILParameterInfo param,

case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Indirect_In_CXX:
return isTypeIndirectForIndirectParamConvention(param.getInterfaceType(),
loweredAddresses);
case ParameterConvention::Indirect_Inout:
Expand Down
1 change: 1 addition & 0 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,7 @@ static char getParamConvention(ParameterConvention conv) {
case ParameterConvention::Indirect_Inout: return 'l';
case ParameterConvention::Indirect_InoutAliasable: return 'b';
case ParameterConvention::Indirect_In_Guaranteed: return 'n';
case ParameterConvention::Indirect_In_CXX: return 'C';
case ParameterConvention::Direct_Owned: return 'x';
case ParameterConvention::Direct_Unowned: return 'y';
case ParameterConvention::Direct_Guaranteed: return 'g';
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6757,6 +6757,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In_Guaranteed:
llvm_unreachable("callee convention cannot be indirect");
case ParameterConvention::Pack_Guaranteed:
Expand Down Expand Up @@ -7526,6 +7527,7 @@ StringRef swift::getStringForParameterConvention(ParameterConvention conv) {
case ParameterConvention::Indirect_In_Guaranteed: return "@in_guaranteed ";
case ParameterConvention::Indirect_Inout: return "@inout ";
case ParameterConvention::Indirect_InoutAliasable: return "@inout_aliasable ";
case ParameterConvention::Indirect_In_CXX: return "@in_cxx ";
case ParameterConvention::Direct_Owned: return "@owned ";
case ParameterConvention::Direct_Unowned: return "";
case ParameterConvention::Direct_Guaranteed: return "@guaranteed ";
Expand Down
1 change: 1 addition & 0 deletions lib/Demangling/Demangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2161,6 +2161,7 @@ NodePointer Demangler::demangleImplParamConvention(Node::Kind ConvKind) {
case 'l': attr = "@inout"; break;
case 'b': attr = "@inout_aliasable"; break;
case 'n': attr = "@in_guaranteed"; break;
case 'C': attr = "@in_cxx"; break;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be documented in docs/ABI/Mangling.rst.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case 'x': attr = "@owned"; break;
case 'g': attr = "@guaranteed"; break;
case 'e': attr = "@deallocating"; break;
Expand Down
1 change: 1 addition & 0 deletions lib/Demangling/Remangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2107,6 +2107,7 @@ ManglingError Remangler::mangleImplFunctionType(Node *node, unsigned depth) {
.Case("@inout", 'l')
.Case("@inout_aliasable", 'b')
.Case("@in_guaranteed", 'n')
.Case("@in_cxx", 'C')
.Case("@in_constant", 'c')
.Case("@owned", 'x')
.Case("@guaranteed", 'g')
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/GenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,7 @@ const TypeInfo &SignatureExpansion::expand(SILParameterInfo param) {
switch (auto conv = param.getConvention()) {
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Indirect_In_CXX:
addIndirectValueParameterAttributes(IGM, Attrs, ti, ParamIRTypes.size());
addPointerParameter(IGM.getStorageType(getSILFuncConventions().getSILType(
param, IGM.getMaximalTypeExpansionContext())));
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/GenDistributed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ void DistributedAccessor::decodeArgument(unsigned argumentIdx,
}

switch (param.getConvention()) {
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In: {
// The only way to load opaque type is to allocate a temporary
// variable on the stack for it and initialize from the given address
Expand Down
5 changes: 5 additions & 0 deletions lib/IRGen/GenFunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,7 @@ CanType irgen::getArgumentLoweringType(CanType type, SILParameterInfo paramInfo,
// address.
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Indirect_In_CXX:
if (isNoEscape)
return CanInOutType::get(type);
else
Expand Down Expand Up @@ -1520,6 +1521,7 @@ static llvm::Value *emitPartialApplicationForwarder(
break;
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_Guaranteed:
case ParameterConvention::Pack_Guaranteed:
Expand Down Expand Up @@ -1631,6 +1633,7 @@ static llvm::Value *emitPartialApplicationForwarder(
// - we received as unowned and are passing as guaranteed
auto argConvention = conventions[0];
switch (argConvention) {
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In:
case ParameterConvention::Direct_Owned:
if (!consumesContext) subIGF.emitNativeStrongRetain(rawData, subIGF.getDefaultAtomicity());
Expand Down Expand Up @@ -1725,6 +1728,7 @@ static llvm::Value *emitPartialApplicationForwarder(

Explosion param;
switch (fieldConvention) {
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In: {

auto initStackCopy = [&addressesToDeallocate, &needsAllocas, &param,
Expand Down Expand Up @@ -2313,6 +2317,7 @@ std::optional<StackAddress> irgen::emitFunctionPartialApplication(
switch (argConventions[i]) {
// Take indirect value arguments out of memory.
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Indirect_In_Guaranteed: {
if (outType->isNoEscape()) {
cast<LoadableTypeInfo>(fieldLayout.getType())
Expand Down
1 change: 1 addition & 0 deletions lib/IRGen/GenObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,7 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
case ParameterConvention::Indirect_In:
case ParameterConvention::Indirect_Inout:
case ParameterConvention::Indirect_InoutAliasable:
case ParameterConvention::Indirect_In_CXX:
case ParameterConvention::Pack_Guaranteed:
case ParameterConvention::Pack_Owned:
case ParameterConvention::Pack_Inout:
Expand Down
Loading