[all-+0] Add a new convention for setters: DefaultSetterConventions.

In a situation where normal arguments are +0, we want setters to still take
normal parameters at +1 since in most cases setters will be taking a parameter
that is being forwarded into to be store into a field.

Since this doesn't actually change the current ParameterConvention for setter
normal arguments, this is NFC.

rdar://34222540
This commit is contained in:
Michael Gottesman
2017-11-19 00:00:20 -08:00
parent 007898347e
commit a8b1917512
3 changed files with 29 additions and 0 deletions

View File

@@ -227,6 +227,10 @@ struct SILDeclRef {
bool isFunc() const {
return kind == Kind::Func;
}
/// True if the SILDeclRef references a setter function.
bool isSetter() const;
/// True if the SILDeclRef references a constructor entry point.
bool isConstructor() const {
return kind == Kind::Allocator || kind == Kind::Initializer;

View File

@@ -484,6 +484,12 @@ FuncDecl *SILDeclRef::getFuncDecl() const {
return dyn_cast<FuncDecl>(getDecl());
}
bool SILDeclRef::isSetter() const {
if (!hasFuncDecl())
return false;
return getFuncDecl()->isSetter();
}
AbstractFunctionDecl *SILDeclRef::getAbstractFunctionDecl() const {
return dyn_cast<AbstractFunctionDecl>(getDecl());
}

View File

@@ -1131,6 +1131,17 @@ struct DefaultInitializerConventions : DefaultConventions {
}
};
/// The default conventions for Swift setter acccessors.
///
/// These take self at +0, but all other parameters at +1. This is because we
/// assume that setter parameters are likely to be values to be forwarded into
/// memory. Thus by passing in the +1 value, we avoid a potential copy in that
/// case.
struct DefaultSetterConventions : DefaultConventions {
DefaultSetterConventions()
: DefaultConventions(NormalParameterConvention::Owned) {}
};
/// The default conventions for ObjC blocks.
struct DefaultBlockConventions : Conventions {
DefaultBlockConventions() : Conventions(ConventionsKind::DefaultBlock) {}
@@ -1204,6 +1215,14 @@ static CanSILFunctionType getNativeSILFunctionType(
constant, witnessMethodConformance);
case SILDeclRef::Kind::Func:
// If we have a setter, use the special setter convention. This ensures
// that we take normal parameters at +1.
if (constant && constant->isSetter()) {
return getSILFunctionType(M, origType, substInterfaceType, extInfo,
DefaultSetterConventions(), ForeignInfo(),
constant, witnessMethodConformance);
}
LLVM_FALLTHROUGH;
case SILDeclRef::Kind::Allocator:
case SILDeclRef::Kind::Destroyer:
case SILDeclRef::Kind::GlobalAccessor: