[SILGen] Teach SILGen to emit property wrapper generator functions that

take in a projected value.
This commit is contained in:
Holly Borla
2021-02-24 19:36:01 -08:00
parent 13692fefde
commit 648c5753df
21 changed files with 176 additions and 10 deletions

View File

@@ -132,6 +132,8 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
case SILDeclRef::Kind::StoredPropertyInitializer:
case SILDeclRef::Kind::PropertyWrapperBackingInitializer:
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
case SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue:
return getMagicFunctionName(cast<VarDecl>(ref.getDecl())->getDeclContext());
case SILDeclRef::Kind::IVarInitializer:
return getMagicFunctionName(cast<ClassDecl>(ref.getDecl()));
case SILDeclRef::Kind::IVarDestroyer:
@@ -896,9 +898,10 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
}
// For a property wrapper backing initializer, form a parameter list
// containing the wrapped value.
// containing the wrapped or projected value.
ParameterList *params = nullptr;
if (function.kind == SILDeclRef::Kind::PropertyWrapperBackingInitializer) {
if (function.kind == SILDeclRef::Kind::PropertyWrapperBackingInitializer ||
function.kind == SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue) {
auto &ctx = getASTContext();
auto param = new (ctx) ParamDecl(SourceLoc(), SourceLoc(),
ctx.getIdentifier("$input_value"),
@@ -906,8 +909,18 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
ctx.getIdentifier("$input_value"),
dc);
param->setSpecifier(ParamSpecifier::Owned);
param->setImplicit();
auto vd = cast<VarDecl>(function.getDecl());
param->setInterfaceType(vd->getPropertyWrapperInitValueInterfaceType());
if (function.kind == SILDeclRef::Kind::PropertyWrapperBackingInitializer) {
param->setInterfaceType(vd->getPropertyWrapperInitValueInterfaceType());
} else {
auto *placeholder = vd->getPropertyWrapperBackingPropertyInfo().getProjectedValuePlaceholder();
auto interfaceType = placeholder->getType();
if (interfaceType->hasArchetype())
interfaceType = interfaceType->mapTypeOutOfContext();
param->setInterfaceType(interfaceType);
}
params = ParameterList::create(ctx, SourceLoc(), {param}, SourceLoc());
}
@@ -935,6 +948,16 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
maybeEmitValueOfLocalVarDecl(param, AccessKind::Read));
assert(value == wrappedInfo.getInitFromWrappedValue());
} else if (function.kind == SILDeclRef::Kind::PropertyWrapperInitFromProjectedValue) {
auto var = cast<VarDecl>(function.getDecl());
auto wrappedInfo = var->getPropertyWrapperBackingPropertyInfo();
auto param = params->get(0);
auto *placeholder = wrappedInfo.getProjectedValuePlaceholder();
opaqueValue.emplace(
*this, placeholder->getOpaqueValuePlaceholder(),
maybeEmitValueOfLocalVarDecl(param, AccessKind::Read));
assert(value == wrappedInfo.getInitFromProjectedValue());
}
emitReturnExpr(Loc, value);