Skip to content

Commit 94c596e

Browse files
authored
Merge pull request #11937 from slavapestov/serialize-default-argument-generators
Serialize SIL for default argument generators in Swift 4 mode
2 parents 91f56a9 + d736501 commit 94c596e

File tree

14 files changed

+203
-53
lines changed

14 files changed

+203
-53
lines changed

include/swift/AST/Decl.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ class alignas(1 << DeclAlignInBits) Decl {
367367
unsigned BodyKind : 3;
368368

369369
/// Number of curried parameter lists.
370-
unsigned NumParameterLists : 6;
370+
unsigned NumParameterLists : 5;
371371

372372
/// Whether we are overridden later.
373373
unsigned Overridden : 1;
@@ -380,6 +380,9 @@ class alignas(1 << DeclAlignInBits) Decl {
380380

381381
/// Whether NeedsNewVTableEntry is valid.
382382
unsigned HasComputedNeedsNewVTableEntry : 1;
383+
384+
/// The ResilienceExpansion to use for default arguments.
385+
unsigned DefaultArgumentResilienceExpansion : 1;
383386
};
384387
enum { NumAbstractFunctionDeclBits = NumValueDeclBits + 13 };
385388
static_assert(NumAbstractFunctionDeclBits <= 32, "fits in an unsigned");
@@ -4859,6 +4862,8 @@ class AbstractFunctionDecl : public ValueDecl, public GenericContext {
48594862
AbstractFunctionDeclBits.Throws = Throws;
48604863
AbstractFunctionDeclBits.NeedsNewVTableEntry = false;
48614864
AbstractFunctionDeclBits.HasComputedNeedsNewVTableEntry = false;
4865+
AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion =
4866+
unsigned(ResilienceExpansion::Maximal);
48624867

48634868
// Verify no bitfield truncation.
48644869
assert(AbstractFunctionDeclBits.NumParameterLists == NumParameterLists);
@@ -5076,6 +5081,21 @@ class AbstractFunctionDecl : public ValueDecl, public GenericContext {
50765081
/// Resolved during type checking
50775082
void setIsOverridden() { AbstractFunctionDeclBits.Overridden = true; }
50785083

5084+
/// The ResilienceExpansion for default arguments.
5085+
///
5086+
/// In Swift 4 mode, default argument expressions are serialized, and must
5087+
/// obey the restrictions imposed upon inlineable function bodies.
5088+
ResilienceExpansion getDefaultArgumentResilienceExpansion() const {
5089+
return ResilienceExpansion(
5090+
AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion);
5091+
}
5092+
5093+
/// Set the ResilienceExpansion for default arguments.
5094+
void setDefaultArgumentResilienceExpansion(ResilienceExpansion expansion) {
5095+
AbstractFunctionDeclBits.DefaultArgumentResilienceExpansion =
5096+
unsigned(expansion);
5097+
}
5098+
50795099
/// Set information about the foreign error convention used by this
50805100
/// declaration.
50815101
void setForeignErrorConvention(const ForeignErrorConvention &convention);

include/swift/AST/Initializer.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,26 +154,16 @@ class DefaultArgumentInitializer : public Initializer {
154154
public:
155155
explicit DefaultArgumentInitializer(DeclContext *parent, unsigned index)
156156
: Initializer(InitializerKind::DefaultArgument, parent) {
157-
SpareBits = (unsigned(ResilienceExpansion::Maximal) | index << 1);
157+
SpareBits = index;
158158
}
159159

160-
unsigned getIndex() const { return SpareBits >> 1; }
161-
162-
ResilienceExpansion getResilienceExpansion() const {
163-
return ResilienceExpansion(SpareBits & 1);
164-
}
160+
unsigned getIndex() const { return SpareBits; }
165161

166162
/// Change the parent of this context. This is necessary because
167163
/// the function signature is parsed before the function
168164
/// declaration/expression itself is built.
169165
void changeFunction(AbstractFunctionDecl *parent);
170166

171-
/// Change the resilience expansion of this context, necessary
172-
/// for the same reason as above.
173-
void changeResilienceExpansion(ResilienceExpansion expansion) {
174-
SpareBits = (SpareBits & ~1) | unsigned(expansion);
175-
}
176-
177167
static bool classof(const DeclContext *DC) {
178168
if (auto init = dyn_cast<Initializer>(DC))
179169
return classof(init);

include/swift/Serialization/ModuleFormat.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ const uint16_t VERSION_MAJOR = 0;
5454
/// in source control, you should also update the comment to briefly
5555
/// describe what change you made. The content of this comment isn't important;
5656
/// it just ensures a conflict if two people change the module format.
57-
const uint16_t VERSION_MINOR = 365; // KeyPathInst operands
57+
const uint16_t VERSION_MINOR = 366; // Last change: default argument resilience expansion
5858

5959
using DeclID = PointerEmbeddedInt<unsigned, 31>;
6060
using DeclIDField = BCFixed<31>;
@@ -388,6 +388,13 @@ enum class EnumElementRawValueKind : uint8_t {
388388
/// TODO: Float, string, char, etc.
389389
};
390390

391+
// These IDs must \em not be renumbered or reordered without incrementing
392+
// VERSION_MAJOR.
393+
enum class ResilienceExpansion : uint8_t {
394+
Minimal = 0,
395+
Maximal,
396+
};
397+
391398
using EnumElementRawValueKindField = BCFixed<4>;
392399

393400
/// The various types of blocks that can occur within a serialized Swift
@@ -893,6 +900,7 @@ namespace decls_block {
893900
DeclIDField, // overridden decl
894901
AccessLevelField, // access level
895902
BCFixed<1>, // requires a new vtable slot
903+
BCFixed<1>, // default argument resilience expansion
896904
BCFixed<1>, // 'required' but overridden is not (used for recovery)
897905
BCVBR<5>, // number of parameter name components
898906
BCArray<IdentifierIDField> // name components,
@@ -957,6 +965,7 @@ namespace decls_block {
957965
AddressorKindField, // addressor kind
958966
AccessLevelField, // access level
959967
BCFixed<1>, // requires a new vtable slot
968+
BCFixed<1>, // default argument resilience expansion
960969
BCArray<IdentifierIDField> // name components,
961970
// followed by TypeID dependencies
962971
// The record is trailed by:

lib/AST/DeclContext.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -519,8 +519,10 @@ ResilienceExpansion DeclContext::getResilienceExpansion() const {
519519
for (const auto *dc = this; dc->isLocalContext(); dc = dc->getParent()) {
520520
// Default argument initializer contexts have their resilience expansion
521521
// set when they're type checked.
522-
if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(dc))
523-
return DAI->getResilienceExpansion();
522+
if (auto *DAI = dyn_cast<DefaultArgumentInitializer>(dc)) {
523+
return cast<AbstractFunctionDecl>(dc->getParent())
524+
->getDefaultArgumentResilienceExpansion();
525+
}
524526

525527
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(dc)) {
526528
// If the function is a nested function, we will serialize its body if

lib/SIL/SILDeclRef.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#include "swift/AST/AnyFunctionRef.h"
1616
#include "swift/AST/ASTContext.h"
1717
#include "swift/AST/ASTMangler.h"
18+
#include "swift/AST/Initializer.h"
19+
#include "swift/AST/ParameterList.h"
1820
#include "swift/ClangImporter/ClangImporter.h"
1921
#include "swift/ClangImporter/ClangModule.h"
2022
#include "swift/SIL/SILLinkage.h"
@@ -538,6 +540,19 @@ IsSerialized_t SILDeclRef::isSerialized() const {
538540
dc = closure->getLocalContext();
539541
else {
540542
auto *d = getDecl();
543+
544+
// Default argument generators are serialized if the function was
545+
// type-checked in Swift 4 mode.
546+
if (kind == SILDeclRef::Kind::DefaultArgGenerator) {
547+
auto *afd = cast<AbstractFunctionDecl>(d);
548+
switch (afd->getDefaultArgumentResilienceExpansion()) {
549+
case ResilienceExpansion::Minimal:
550+
return IsSerialized;
551+
case ResilienceExpansion::Maximal:
552+
return IsNotSerialized;
553+
}
554+
}
555+
541556
dc = getDecl()->getInnermostDeclContext();
542557

543558
// Enum element constructors are serialized if the enum is

lib/SILGen/SILGen.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -649,11 +649,10 @@ emitMarkFunctionEscapeForTopLevelCodeGlobals(SILLocation loc,
649649

650650
void SILGenModule::emitAbstractFuncDecl(AbstractFunctionDecl *AFD) {
651651
// Emit any default argument generators.
652-
{
653-
auto paramLists = AFD->getParameterLists();
654-
if (AFD->getDeclContext()->isTypeContext())
655-
paramLists = paramLists.slice(1);
656-
emitDefaultArgGenerators(AFD, paramLists);
652+
if (!isa<DestructorDecl>(AFD)) {
653+
unsigned paramListIndex = AFD->getDeclContext()->isTypeContext() ? 1 : 0;
654+
auto *paramList = AFD->getParameterLists()[paramListIndex];
655+
emitDefaultArgGenerators(AFD, paramList);
657656
}
658657

659658
// If this is a function at global scope, it may close over a global variable.
@@ -1015,15 +1014,13 @@ void SILGenModule::emitGlobalGetter(VarDecl *global,
10151014
}
10161015

10171016
void SILGenModule::emitDefaultArgGenerators(SILDeclRef::Loc decl,
1018-
ArrayRef<ParameterList*> paramLists) {
1017+
ParameterList *paramList) {
10191018
unsigned index = 0;
1020-
for (auto paramList : paramLists) {
1021-
for (auto param : *paramList) {
1022-
if (auto defaultArg = param->getDefaultValue())
1023-
emitDefaultArgGenerator(SILDeclRef::getDefaultArgGenerator(decl, index),
1024-
defaultArg, param->getDefaultArgumentKind());
1025-
++index;
1026-
}
1019+
for (auto param : *paramList) {
1020+
if (auto defaultArg = param->getDefaultValue())
1021+
emitDefaultArgGenerator(SILDeclRef::getDefaultArgGenerator(decl, index),
1022+
defaultArg, param->getDefaultArgumentKind());
1023+
++index;
10271024
}
10281025
}
10291026

lib/SILGen/SILGen.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,9 @@ class LLVM_LIBRARY_VISIBILITY SILGenModule : public ASTVisitor<SILGenModule> {
271271
/// Emits the stored property initializer for the given pattern.
272272
void emitStoredPropertyInitialization(PatternBindingDecl *pd, unsigned i);
273273

274-
/// Emits the default argument generator for the given function.
274+
/// Emits default argument generators for the given parameter list.
275275
void emitDefaultArgGenerators(SILDeclRef::Loc decl,
276-
ArrayRef<ParameterList*> paramLists);
276+
ParameterList *paramList);
277277

278278
/// Emits the curry thunk between two uncurry levels of a function.
279279
void emitCurryThunk(SILDeclRef thunk);

lib/Sema/TypeCheckStmt.cpp

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,14 +1279,6 @@ static void checkDefaultArguments(TypeChecker &tc,
12791279
ParameterList *params,
12801280
unsigned &nextArgIndex,
12811281
AbstractFunctionDecl *func) {
1282-
// In Swift 4 mode, default argument bodies are inlined into the
1283-
// caller.
1284-
auto expansion = func->getResilienceExpansion();
1285-
if (!tc.Context.isSwiftVersion3() &&
1286-
func->getFormalAccessScope(/*useDC=*/nullptr,
1287-
/*respectVersionedAttr=*/true).isPublic())
1288-
expansion = ResilienceExpansion::Minimal;
1289-
12901282
for (auto &param : *params) {
12911283
++nextArgIndex;
12921284
if (!param->getDefaultValue() || !param->hasType() ||
@@ -1296,9 +1288,6 @@ static void checkDefaultArguments(TypeChecker &tc,
12961288
Expr *e = param->getDefaultValue();
12971289
auto initContext = param->getDefaultArgumentInitContext();
12981290

1299-
cast<DefaultArgumentInitializer>(initContext)
1300-
->changeResilienceExpansion(expansion);
1301-
13021291
// Type-check the initializer, then flag that we did so.
13031292
auto resultTy = tc.typeCheckExpression(
13041293
e, initContext, TypeLoc::withoutLoc(param->getType()),
@@ -1317,6 +1306,24 @@ static void checkDefaultArguments(TypeChecker &tc,
13171306
}
13181307
}
13191308

1309+
/// Check the default arguments that occur within this pattern.
1310+
static void checkDefaultArguments(TypeChecker &tc,
1311+
AbstractFunctionDecl *func) {
1312+
// In Swift 4 mode, default argument bodies are inlined into the
1313+
// caller.
1314+
auto expansion = func->getResilienceExpansion();
1315+
if (!tc.Context.isSwiftVersion3() &&
1316+
func->getFormalAccessScope(/*useDC=*/nullptr,
1317+
/*respectVersionedAttr=*/true).isPublic())
1318+
expansion = ResilienceExpansion::Minimal;
1319+
1320+
func->setDefaultArgumentResilienceExpansion(expansion);
1321+
1322+
unsigned nextArgIndex = 0;
1323+
for (auto paramList : func->getParameterLists())
1324+
checkDefaultArguments(tc, paramList, nextArgIndex, func);
1325+
}
1326+
13201327
bool TypeChecker::typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD,
13211328
SourceLoc EndTypeCheckLoc) {
13221329
validateDecl(AFD);
@@ -1358,10 +1365,7 @@ bool TypeChecker::typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD) {
13581365
// named function or an anonymous func expression.
13591366
bool TypeChecker::typeCheckFunctionBodyUntil(FuncDecl *FD,
13601367
SourceLoc EndTypeCheckLoc) {
1361-
// Check the default argument definitions.
1362-
unsigned nextArgIndex = 0;
1363-
for (auto paramList : FD->getParameterLists())
1364-
checkDefaultArguments(*this, paramList, nextArgIndex, FD);
1368+
checkDefaultArguments(*this, FD);
13651369

13661370
// Clang imported inline functions do not have a Swift body to
13671371
// typecheck.
@@ -1464,10 +1468,7 @@ static bool isKnownEndOfConstructor(ASTNode N) {
14641468

14651469
bool TypeChecker::typeCheckConstructorBodyUntil(ConstructorDecl *ctor,
14661470
SourceLoc EndTypeCheckLoc) {
1467-
// Check the default argument definitions.
1468-
unsigned nextArgIndex = 0;
1469-
for (auto paramList : ctor->getParameterLists())
1470-
checkDefaultArguments(*this, paramList, nextArgIndex, ctor);
1471+
checkDefaultArguments(*this, ctor);
14711472

14721473
BraceStmt *body = ctor->getBody();
14731474
if (!body)

lib/Serialization/Deserialization.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,17 @@ getActualSelfAccessKind(uint8_t raw) {
19421942
return None;
19431943
}
19441944

1945+
static
1946+
Optional<swift::ResilienceExpansion> getActualResilienceExpansion(uint8_t raw) {
1947+
switch (serialization::ResilienceExpansion(raw)) {
1948+
case serialization::ResilienceExpansion::Minimal:
1949+
return swift::ResilienceExpansion::Minimal;
1950+
case serialization::ResilienceExpansion::Maximal:
1951+
return swift::ResilienceExpansion::Maximal;
1952+
}
1953+
return None;
1954+
}
1955+
19451956
void ModuleFile::configureStorage(AbstractStorageDecl *decl,
19461957
unsigned rawStorageKind,
19471958
serialization::DeclID getter,
@@ -2570,6 +2581,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
25702581
TypeID interfaceID;
25712582
DeclID overriddenID;
25722583
bool needsNewVTableEntry, firstTimeRequired;
2584+
uint8_t rawDefaultArgumentResilienceExpansion;
25732585
unsigned numArgNames;
25742586
ArrayRef<uint64_t> argNameAndDependencyIDs;
25752587

@@ -2581,6 +2593,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
25812593
overriddenID,
25822594
rawAccessLevel,
25832595
needsNewVTableEntry,
2596+
rawDefaultArgumentResilienceExpansion,
25842597
firstTimeRequired,
25852598
numArgNames,
25862599
argNameAndDependencyIDs);
@@ -2687,6 +2700,16 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
26872700
if (auto overriddenCtor = cast_or_null<ConstructorDecl>(overridden.get()))
26882701
ctor->setOverriddenDecl(overriddenCtor);
26892702
ctor->setNeedsNewVTableEntry(needsNewVTableEntry);
2703+
2704+
if (auto defaultArgumentResilienceExpansion = getActualResilienceExpansion(
2705+
rawDefaultArgumentResilienceExpansion)) {
2706+
ctor->setDefaultArgumentResilienceExpansion(
2707+
*defaultArgumentResilienceExpansion);
2708+
} else {
2709+
error();
2710+
return nullptr;
2711+
}
2712+
26902713
break;
26912714
}
26922715

@@ -2825,6 +2848,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
28252848
DeclID overriddenID;
28262849
DeclID accessorStorageDeclID;
28272850
bool needsNewVTableEntry;
2851+
uint8_t rawDefaultArgumentResilienceExpansion;
28282852
ArrayRef<uint64_t> nameAndDependencyIDs;
28292853

28302854
decls_block::FuncLayout::readRecord(scratch, contextID, isImplicit,
@@ -2837,6 +2861,7 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
28372861
numNameComponentsBiased,
28382862
rawAddressorKind, rawAccessLevel,
28392863
needsNewVTableEntry,
2864+
rawDefaultArgumentResilienceExpansion,
28402865
nameAndDependencyIDs);
28412866

28422867
// Resolve the name ids.
@@ -2974,6 +2999,16 @@ ModuleFile::getDeclChecked(DeclID DID, Optional<DeclContext *> ForcedContext) {
29742999
fn->setImplicit();
29753000
fn->setDynamicSelf(hasDynamicSelf);
29763001
fn->setNeedsNewVTableEntry(needsNewVTableEntry);
3002+
3003+
if (auto defaultArgumentResilienceExpansion = getActualResilienceExpansion(
3004+
rawDefaultArgumentResilienceExpansion)) {
3005+
fn->setDefaultArgumentResilienceExpansion(
3006+
*defaultArgumentResilienceExpansion);
3007+
} else {
3008+
error();
3009+
return nullptr;
3010+
}
3011+
29773012
break;
29783013
}
29793014

lib/Serialization/DeserializeSIL.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ static SILDeclRef getSILDeclRef(ModuleFile *MF,
707707
"Expect 5 numbers for SILDeclRef");
708708
SILDeclRef DRef(cast<ValueDecl>(MF->getDecl(ListOfValues[NextIdx])),
709709
(SILDeclRef::Kind)ListOfValues[NextIdx+1],
710-
(ResilienceExpansion)ListOfValues[NextIdx+2],
710+
(swift::ResilienceExpansion)ListOfValues[NextIdx+2],
711711
/*isCurried=*/false, ListOfValues[NextIdx+4] > 0);
712712
if (ListOfValues[NextIdx+3] < DRef.getUncurryLevel())
713713
DRef = DRef.asCurried();

0 commit comments

Comments
 (0)