Skip to content

Commit 38c61d7

Browse files
authored
Merge pull request #85054 from kavon/opaque-values/fixes-3
OpaqueValues: add support for property wrappers
2 parents 301f51e + 19bd65c commit 38c61d7

17 files changed

+239
-131
lines changed

include/swift/SIL/SILFunctionConventions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,9 @@ class SILFunctionConventions {
515515
- getNumIndirectSILErrorResults()];
516516
}
517517

518+
/// WARNING: Do not use this from SILGen!
519+
/// Use methods such as `isSILIndirect` or query the ParameterInfo instead.
520+
///
518521
/// Return the SIL argument convention of apply/entry argument at
519522
/// the given argument index.
520523
SILArgumentConvention getSILArgumentConvention(unsigned index) const;

lib/SIL/IR/SILArgument.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ SILParameterInfo SILFunctionArgument::getKnownParameterInfo() const {
8787
return getFunction()->getConventions().getParamInfoForSILArg(getIndex());
8888
}
8989

90+
/// WARNING: Do not use this from SILGen!
91+
/// Use methods such as `isSILIndirect` or query the ParameterInfo instead.
9092
SILArgumentConvention
9193
SILFunctionConventions::getSILArgumentConvention(unsigned index) const {
9294
assert(index < getNumSILArguments());

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3191,9 +3191,9 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
31913191
CanSILFunctionType initTy = initFn->getType().castTo<SILFunctionType>();
31923192
SILFunctionConventions initConv(initTy, AI->getModule());
31933193

3194-
require(initConv.getNumIndirectSILResults() ==
3194+
require(initConv.getResults().size() ==
31953195
AI->getNumInitializedProperties(),
3196-
"init function has invalid number of indirect results");
3196+
"init function has invalid number of results");
31973197
checkAssigOrInitInstAccessorArgs(Src->getType(), initConv);
31983198
}
31993199

lib/SILGen/SILGenConstructor.cpp

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,35 +1822,46 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
18221822
RegularLocation Loc(value);
18231823
Loc.markAutoGenerated();
18241824

1825-
auto loweredFuncDeclTy = F.getLoweredFunctionType();
1826-
bool isLocalContext = vd->getDeclContext()->isLocalContext();
1827-
1828-
auto createArgument = [&](VarDecl *property, SILType type,
1829-
bool markUninitialized = false) {
1830-
auto *arg = ParamDecl::createImplicit(
1831-
getASTContext(), property->getBaseIdentifier(),
1832-
property->getBaseIdentifier(), property->getInterfaceType(),
1833-
declContext, ParamSpecifier::InOut);
1834-
1835-
RegularLocation loc(property);
1836-
loc.markAutoGenerated();
1837-
1838-
SILValue argValue = F.begin()->createFunctionArgument(type, arg);
1839-
if (markUninitialized) {
1840-
argValue = B.createMarkUninitializedOut(loc, argValue);
1841-
}
1825+
auto backingStorage = vd->getPropertyWrapperBackingProperty();
1826+
Type returnTy = vd->getPropertyWrapperBackingPropertyType();
1827+
1828+
/// This thunk uses its own return convention, unlike a usual function,
1829+
/// by always returning its result indirect, even if the type is trivial.
1830+
///
1831+
/// Because of that, much of the work that would normally be handled in SILGen
1832+
/// using standard function conventions is done manually here, when
1833+
/// -enable-sil-opaque-values is disabled. Part of the reason for this is
1834+
/// that calls to this accessor are lowered after DefiniteInitialization.
1835+
if (useLoweredAddresses()) {
1836+
returnTy = TupleType::getEmpty(F.getASTContext());
1837+
1838+
auto loweredFuncDeclTy = F.getLoweredFunctionType();
1839+
auto createArgument = [&](VarDecl *property, SILType type,
1840+
bool markUninitialized = false) {
1841+
auto *arg = ParamDecl::createImplicit(
1842+
getASTContext(), property->getBaseIdentifier(),
1843+
property->getBaseIdentifier(), property->getInterfaceType(),
1844+
declContext, ParamSpecifier::InOut);
1845+
1846+
RegularLocation loc(property);
1847+
loc.markAutoGenerated();
1848+
1849+
SILValue argValue = F.begin()->createFunctionArgument(type, arg);
1850+
if (markUninitialized) {
1851+
argValue = B.createMarkUninitializedOut(loc, argValue);
1852+
}
18421853

1843-
VarLocs[arg] = VarLoc(argValue, SILAccessEnforcement::Static);
1844-
InitAccessorArgumentMappings[property] = arg;
1845-
};
1854+
VarLocs[arg] = VarLoc(argValue, SILAccessEnforcement::Static);
1855+
InitAccessorArgumentMappings[property] = arg;
1856+
};
18461857

1847-
// Emit @out backing storage argument
1848-
auto backingStorage = vd->getPropertyWrapperBackingProperty();
1849-
auto backingStorageTy = getSILTypeInContext(
1850-
loweredFuncDeclTy->getResults()[0], loweredFuncDeclTy);
1851-
createArgument(backingStorage, backingStorageTy, /*markUninitialized=*/true);
1858+
// Emit @out backing storage argument
1859+
auto backingStorageTy = getSILTypeInContext(
1860+
loweredFuncDeclTy->getResults()[0], loweredFuncDeclTy);
1861+
createArgument(backingStorage, backingStorageTy, /*markUninitialized=*/true);
1862+
}
18521863

1853-
// Emit `newValue` argument
1864+
// Create the `newValue` argument
18541865
ParameterList *params = nullptr;
18551866
auto newValueParam = new (ctx)
18561867
ParamDecl(SourceLoc(), SourceLoc(), ctx.getIdentifier("$input_value"),
@@ -1864,9 +1875,10 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
18641875

18651876
// Nominal contexts have an extra trailing metatype argument,
18661877
// local contexts do not
1878+
const bool isLocalContext = vd->getDeclContext()->isLocalContext();
18671879
auto numIgnoredParams = isLocalContext ? 0 : 1;
18681880
emitBasicProlog(declContext, params,
1869-
/*selfParam=*/nullptr, TupleType::getEmpty(F.getASTContext()),
1881+
/*selfParam=*/nullptr, returnTy,
18701882
/*errorType=*/std::nullopt,
18711883
/*throwsLoc=*/SourceLoc(),
18721884
/*ignored parameters*/ numIgnoredParams);
@@ -1875,9 +1887,14 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
18751887
if (!isLocalContext)
18761888
emitConstructorMetatypeArg(*this, vd);
18771889

1878-
prepareEpilog(declContext, TupleType::getEmpty(F.getASTContext()),
1890+
prepareEpilog(declContext, returnTy,
18791891
std::nullopt, CleanupLocation(Loc));
18801892

1893+
if (EmitProfilerIncrement)
1894+
emitProfilerIncrement(value);
1895+
1896+
FullExpr scope(Cleanups, CleanupLocation(value));
1897+
18811898
// Create an opaque value binding that maps 'newValue' to the wrapper's
18821899
// wrappedValue AST placeholder. This makes the argument available when
18831900
// init(wrappedValue:) is emitted
@@ -1889,16 +1906,19 @@ void SILGenFunction::emitPropertyWrappedFieldInitAccessor(
18891906
maybeEmitValueOfLocalVarDecl(newValueParam, AccessKind::Read));
18901907
assert(value == initInfo.getInitFromWrappedValue());
18911908

1892-
// Prepare InitializationPtr for the @out return buffer
1893-
FullExpr scope(Cleanups, CleanupLocation(value));
1894-
auto backingStorageArg = InitAccessorArgumentMappings[backingStorage];
1895-
auto backingStorageAddr = VarLocs[backingStorageArg].value;
1896-
InitializationPtr init(new KnownAddressInitialization(backingStorageAddr));
1909+
if (useLoweredAddresses()) {
1910+
// Prepare InitializationPtr for the @out return buffer
1911+
auto backingStorageArg = InitAccessorArgumentMappings[backingStorage];
1912+
auto backingStorageAddr = VarLocs[backingStorageArg].value;
1913+
InitializationPtr init(new KnownAddressInitialization(backingStorageAddr));
18971914

1898-
// Intialize the @out buffer with the given expression
1899-
emitExprInto(value, init.get());
1915+
// Intialize the @out buffer with the given expression
1916+
emitExprInto(value, init.get());
1917+
} else {
1918+
emitReturnExpr(Loc, value);
1919+
}
19001920

19011921
// Emit epilog/cleanups
19021922
emitEpilog(Loc);
19031923
mergeCleanupBlocks();
1904-
}
1924+
}

lib/SILGen/SILGenFunction.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,9 +1889,10 @@ SILGenFunction::emitApplyOfSetterToBase(SILLocation loc, SILDeclRef setter,
18891889
assert(base);
18901890

18911891
SILValue capturedBase;
1892-
unsigned argIdx = setterConv.getNumSILArguments() - 1;
1892+
unsigned argIdx = setterConv.getSILArgIndexOfSelf();
1893+
auto paramInfo = setterConv.getParamInfoForSILArg(argIdx);
18931894

1894-
if (setterConv.getSILArgumentConvention(argIdx).isInoutConvention()) {
1895+
if (paramInfo.isIndirectMutating()) {
18951896
capturedBase = base.getValue();
18961897
} else if (base.getType().isAddress() &&
18971898
base.getType().getObjectType() ==
@@ -1981,9 +1982,9 @@ void SILGenFunction::emitAssignOrInit(SILLocation loc, ManagedValue selfValue,
19811982
SILFunctionConventions initConv(initTy, SGM.M);
19821983

19831984
auto newValueArgIdx = initConv.getSILArgIndexOfFirstParam();
1985+
auto newValueParamInfo = initConv.getParamInfoForSILArg(newValueArgIdx);
19841986
// If we need the argument in memory, materialize an address.
1985-
if (initConv.getSILArgumentConvention(newValueArgIdx)
1986-
.isIndirectConvention() &&
1987+
if (initConv.isSILIndirect(newValueParamInfo) &&
19871988
!newValue.getType().isAddress()) {
19881989
newValue = newValue.materialize(*this, loc);
19891990
}

lib/SILGen/SILGenLValue.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1529,8 +1529,10 @@ namespace {
15291529
return cast<AccessorDecl>(Accessor.getFuncDecl());
15301530
}
15311531

1532-
ManagedValue emitValue(SILGenFunction &SGF, SILLocation loc, VarDecl *field,
1533-
ArgumentSource &&value, AccessorKind accessorKind) {
1532+
ManagedValue emitValueForAssignOrInit(SILGenFunction &SGF, SILLocation loc,
1533+
VarDecl *field,
1534+
ArgumentSource &&value,
1535+
AccessorKind accessorKind) {
15341536
auto accessorInfo = SGF.getConstantInfo(
15351537
SGF.getTypeExpansionContext(),
15361538
SILDeclRef(field->getOpaqueAccessor(accessorKind)));
@@ -1554,7 +1556,8 @@ namespace {
15541556
assert(value.isRValue());
15551557
ManagedValue Mval =
15561558
std::move(value).asKnownRValue(SGF).getAsSingleValue(SGF, loc);
1557-
auto param = accessorTy->getParameters()[0];
1559+
auto paramIdx = accessorConv.getSILArgIndexOfFirstParam();
1560+
auto param = accessorConv.getParamInfoForSILArg(paramIdx);
15581561
SILType loweredSubstArgType = Mval.getType();
15591562
if (param.isIndirectInOut()) {
15601563
loweredSubstArgType =
@@ -1573,11 +1576,8 @@ namespace {
15731576
fieldTy->getCanonicalType());
15741577
}
15751578

1576-
auto newValueArgIdx = accessorConv.getNumIndirectSILResults();
15771579
// If we need the argument in memory, materialize an address.
1578-
if (accessorConv.getSILArgumentConvention(newValueArgIdx)
1579-
.isIndirectConvention() &&
1580-
!Mval.getType().isAddress()) {
1580+
if (accessorConv.isSILIndirect(param) && !Mval.getType().isAddress()) {
15811581
Mval = Mval.materialize(SGF, loc);
15821582
}
15831583

@@ -1611,7 +1611,7 @@ namespace {
16111611
override {
16121612
VarDecl *field = cast<VarDecl>(Storage);
16131613
auto Mval =
1614-
emitValue(SGF, loc, field, std::move(value), AccessorKind::Init);
1614+
emitValueForAssignOrInit(SGF, loc, field, std::move(value), AccessorKind::Init);
16151615
SGF.emitAssignOrInit(loc, base, field, Mval, Substitutions);
16161616
}
16171617

@@ -1876,7 +1876,7 @@ namespace {
18761876

18771877
// Create the assign_or_init SIL instruction
18781878
auto Mval =
1879-
emitValue(SGF, loc, field, std::move(value), AccessorKind::Set);
1879+
emitValueForAssignOrInit(SGF, loc, field, std::move(value), AccessorKind::Set);
18801880
auto selfOrLocal = selfMetatype ? base.getValue() : proj.forward(SGF);
18811881
SGF.B.createAssignOrInit(loc, field, selfOrLocal, Mval.forward(SGF),
18821882
initFn.getValue(), setterFn,

lib/SILGen/SILGenProlog.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,19 +1331,18 @@ static void emitCaptureArguments(SILGenFunction &SGF,
13311331
case CaptureKind::Immutable: {
13321332
auto argIndex = SGF.F.begin()->getNumArguments();
13331333
// Non-escaping stored decls are captured as the address of the value.
1334-
auto argConv = SGF.F.getConventions().getSILArgumentConvention(argIndex);
1335-
bool isInOut = (argConv == SILArgumentConvention::Indirect_Inout ||
1336-
argConv == SILArgumentConvention::Indirect_InoutAliasable);
1337-
auto param = SGF.F.getConventions().getParamInfoForSILArg(argIndex);
1338-
if (SGF.F.getConventions().isSILIndirect(param)) {
1334+
auto fnConv = SGF.F.getConventions();
1335+
auto paramInfo = fnConv.getParamInfoForSILArg(argIndex);
1336+
if (fnConv.isSILIndirect(paramInfo)) {
13391337
ty = ty.getAddressType();
13401338
}
13411339
auto *fArg = SGF.F.begin()->createFunctionArgument(ty, VD);
13421340
fArg->setClosureCapture(true);
13431341
arg = SILValue(fArg);
13441342

13451343
if (isNoImplicitCopy && !arg->getType().isMoveOnly()) {
1346-
switch (argConv) {
1344+
// FIXME: this incompatible with -enable-sil-opaque-values
1345+
switch (fnConv.getSILArgumentConvention(argIndex)) {
13471346
case SILArgumentConvention::Indirect_Inout:
13481347
case SILArgumentConvention::Indirect_InoutAliasable:
13491348
case SILArgumentConvention::Indirect_In:
@@ -1377,6 +1376,7 @@ static void emitCaptureArguments(SILGenFunction &SGF,
13771376
// in SIL since it is illegal to capture an inout value in an escaping
13781377
// closure. The later code knows how to handle that we have the
13791378
// mark_unresolved_non_copyable_value here.
1379+
bool isInOut = paramInfo.isIndirectMutating();
13801380
if (isInOut && arg->getType().isMoveOnly()) {
13811381
arg = SGF.B.createMarkUnresolvedNonCopyableValueInst(
13821382
Loc, arg,

0 commit comments

Comments
 (0)