Skip to content

Commit d82137b

Browse files
authored
Merge pull request #17404 from jckarter/trivial-property-descriptors
SILGen: Emit "trivial" property descriptors for properties that withhold no information about their implementation.
2 parents 73d09e5 + 3e4e00c commit d82137b

File tree

20 files changed

+301
-101
lines changed

20 files changed

+301
-101
lines changed

include/swift/AST/Decl.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4229,6 +4229,25 @@ class AbstractStorageDecl : public ValueDecl {
42294229
llvm_unreachable("bad storage kind");
42304230
}
42314231

4232+
/// \brief Return true if this is a VarDecl that has storage associated with
4233+
/// it which can be trivially accessed.
4234+
bool hasTrivialStorage() const {
4235+
switch (getStorageKind()) {
4236+
case Stored:
4237+
case StoredWithTrivialAccessors:
4238+
return true;
4239+
case StoredWithObservers:
4240+
case InheritedWithObservers:
4241+
case Computed:
4242+
case ComputedWithMutableAddress:
4243+
case Addressed:
4244+
case AddressedWithTrivialAccessors:
4245+
case AddressedWithObservers:
4246+
return false;
4247+
}
4248+
llvm_unreachable("bad storage kind");
4249+
}
4250+
42324251
/// \brief Return true if this object has a getter (and, if mutable,
42334252
/// a setter and a materializeForSet).
42344253
bool hasAccessorFunctions() const {
@@ -4457,7 +4476,8 @@ class AbstractStorageDecl : public ValueDecl {
44574476

44584477
/// Determine how this storage declaration should actually be accessed.
44594478
AccessStrategy getAccessStrategy(AccessSemantics semantics,
4460-
AccessKind accessKind) const;
4479+
AccessKind accessKind,
4480+
DeclContext *accessFromDC = nullptr) const;
44614481

44624482
/// \brief Should this declaration behave as if it must be accessed
44634483
/// resiliently, even when we're building a non-resilient module?

include/swift/SIL/SILProperty.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,25 +42,31 @@ class SILProperty : public llvm::ilist_node<SILProperty>,
4242
AbstractStorageDecl *Decl;
4343

4444
/// The key path component that represents its implementation.
45-
KeyPathPatternComponent Component;
45+
Optional<KeyPathPatternComponent> Component;
4646

4747
SILProperty(bool Serialized,
4848
AbstractStorageDecl *Decl,
49-
KeyPathPatternComponent Component)
49+
Optional<KeyPathPatternComponent> Component)
5050
: Serialized(Serialized), Decl(Decl), Component(Component)
5151
{}
5252

5353
public:
5454
static SILProperty *create(SILModule &M,
5555
bool Serialized,
5656
AbstractStorageDecl *Decl,
57-
KeyPathPatternComponent Component);
57+
Optional<KeyPathPatternComponent> Component);
5858

5959
bool isSerialized() const { return Serialized; }
6060

6161
AbstractStorageDecl *getDecl() const { return Decl; }
6262

63-
const KeyPathPatternComponent &getComponent() const { return Component; }
63+
bool isTrivial() const {
64+
return !Component.hasValue();
65+
}
66+
67+
const Optional<KeyPathPatternComponent> &getComponent() const {
68+
return Component;
69+
}
6470

6571
void print(SILPrintContext &Ctx) const;
6672
void dump() const;

include/swift/SIL/TypeLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,8 @@ class TypeConverter {
983983
CanSILBoxType getBoxTypeForEnumElement(SILType enumType,
984984
EnumElementDecl *elt);
985985

986+
bool canStorageUseStoredKeyPathComponent(AbstractStorageDecl *decl);
987+
986988
private:
987989
CanType getLoweredRValueType(AbstractionPattern origType, CanType substType);
988990

lib/AST/Decl.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,8 @@ ValueDecl::getAccessSemanticsFromContext(const DeclContext *UseDC,
14141414

14151415
AccessStrategy
14161416
AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
1417-
AccessKind accessKind) const {
1417+
AccessKind accessKind,
1418+
DeclContext *accessFromDC) const {
14181419
switch (semantics) {
14191420
case AccessSemantics::DirectToStorage:
14201421
switch (getStorageKind()) {
@@ -1481,7 +1482,14 @@ AbstractStorageDecl::getAccessStrategy(AccessSemantics semantics,
14811482
// This is done by using DirectToStorage semantics above, with the
14821483
// understanding that the access semantics are with respect to the
14831484
// resilience domain of the accessor's caller.
1484-
if (isResilient())
1485+
bool resilient;
1486+
if (accessFromDC)
1487+
resilient = isResilient(accessFromDC->getParentModule(),
1488+
ResilienceExpansion::Maximal);
1489+
else
1490+
resilient = isResilient();
1491+
1492+
if (resilient)
14851493
return AccessStrategy::DirectToAccessor;
14861494

14871495
if (storageKind == StoredWithObservers ||

lib/IRGen/GenKeyPath.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,33 @@ IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
12181218
}
12191219

12201220
void IRGenModule::emitSILProperty(SILProperty *prop) {
1221+
if (prop->isTrivial()) {
1222+
// All trivial property descriptors can share a single definition in the
1223+
// translation unit.
1224+
if (!TheTrivialPropertyDescriptor) {
1225+
// Emit a definition if we don't have one yet.
1226+
ConstantInitBuilder builder(*this);
1227+
ConstantStructBuilder fields = builder.beginStruct();
1228+
fields.addInt32(
1229+
_SwiftKeyPathComponentHeader_TrivialPropertyDescriptorMarker);
1230+
auto var = cast<llvm::GlobalVariable>(
1231+
getAddrOfPropertyDescriptor(prop->getDecl(),
1232+
fields.finishAndCreateFuture()));
1233+
var->setConstant(true);
1234+
var->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
1235+
var->setAlignment(4);
1236+
1237+
TheTrivialPropertyDescriptor = var;
1238+
} else {
1239+
auto entity = LinkEntity::forPropertyDescriptor(prop->getDecl());
1240+
auto linkInfo = LinkInfo::get(*this, entity, ForDefinition);
1241+
llvm::GlobalAlias::create(linkInfo.getLinkage(),
1242+
linkInfo.getName(),
1243+
TheTrivialPropertyDescriptor);
1244+
}
1245+
return;
1246+
}
1247+
12211248
ConstantInitBuilder builder(*this);
12221249
ConstantStructBuilder fields = builder.beginStruct();
12231250
fields.setPacked(true);
@@ -1245,7 +1272,7 @@ void IRGenModule::emitSILProperty(SILProperty *prop) {
12451272
[&](GenericRequirement reqt) { requirements.push_back(reqt); });
12461273
}
12471274

1248-
emitKeyPathComponent(*this, fields, prop->getComponent(),
1275+
emitKeyPathComponent(*this, fields, *prop->getComponent(),
12491276
isInstantiableInPlace, genericEnv, requirements,
12501277
prop->getDecl()->getInnermostDeclContext()
12511278
->getInnermostTypeContext()
@@ -1260,6 +1287,7 @@ void IRGenModule::emitSILProperty(SILProperty *prop) {
12601287
getAddrOfPropertyDescriptor(prop->getDecl(),
12611288
fields.finishAndCreateFuture()));
12621289
var->setConstant(true);
1290+
var->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
12631291
// A simple stored component descriptor can fit in four bytes. Anything else
12641292
// needs pointer alignment.
12651293
if (size <= Size(4))

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,8 @@ class IRGenModule {
570570
llvm::PointerType *OpenedErrorTriplePtrTy; /// { %swift.opaque*, %swift.type*, i8** }*
571571
llvm::PointerType *WitnessTablePtrPtrTy; /// i8***
572572

573+
llvm::GlobalVariable *TheTrivialPropertyDescriptor = nullptr;
574+
573575
/// Used to create unique names for class layout types with tail allocated
574576
/// elements.
575577
unsigned TailElemTypeID = 0;

lib/ParseSIL/ParseSIL.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5464,19 +5464,26 @@ bool SILParserTUState::parseSILProperty(Parser &P) {
54645464
}
54655465

54665466
Identifier ComponentKind;
5467-
KeyPathPatternComponent Component;
5467+
Optional<KeyPathPatternComponent> Component;
54685468
SourceLoc ComponentLoc;
54695469
SmallVector<SILType, 4> OperandTypes;
54705470

5471-
if (P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "(")
5472-
|| P.parseIdentifier(ComponentKind, ComponentLoc,
5473-
diag::expected_tok_in_sil_instr, "component kind")
5474-
|| SP.parseKeyPathPatternComponent(Component, OperandTypes,
5475-
ComponentLoc, ComponentKind, InstLoc,
5476-
patternEnv)
5477-
|| P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
5471+
if (P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
54785472
return true;
54795473

5474+
if (!P.consumeIf(tok::r_paren)) {
5475+
KeyPathPatternComponent parsedComponent;
5476+
if (P.parseIdentifier(ComponentKind, ComponentLoc,
5477+
diag::expected_tok_in_sil_instr, "component kind")
5478+
|| SP.parseKeyPathPatternComponent(parsedComponent, OperandTypes,
5479+
ComponentLoc, ComponentKind, InstLoc,
5480+
patternEnv)
5481+
|| P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
5482+
return true;
5483+
5484+
Component = std::move(parsedComponent);
5485+
}
5486+
54805487
SILProperty::create(M, Serialized,
54815488
cast<AbstractStorageDecl>(VD), Component);
54825489
return false;

lib/SIL/SILModule.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ void SILModule::setOptRecordStream(
849849
SILProperty *SILProperty::create(SILModule &M,
850850
bool Serialized,
851851
AbstractStorageDecl *Decl,
852-
KeyPathPatternComponent Component) {
852+
Optional<KeyPathPatternComponent> Component) {
853853
auto prop = new (M) SILProperty(Serialized, Decl, Component);
854854
M.properties.push_back(prop);
855855
return prop;

lib/SIL/SILPrinter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,10 +2648,10 @@ void SILProperty::print(SILPrintContext &Ctx) const {
26482648
if (auto sig = getDecl()->getInnermostDeclContext()
26492649
->getGenericSignatureOfContext()) {
26502650
sig->getCanonicalSignature()->print(OS, Options);
2651-
OS << ' ';
26522651
}
2653-
OS << '(';
2654-
SILPrinter(Ctx).printKeyPathPatternComponent(getComponent());
2652+
OS << " (";
2653+
if (auto component = getComponent())
2654+
SILPrinter(Ctx).printKeyPathPatternComponent(*component);
26552655
OS << ")\n";
26562656
}
26572657

lib/SIL/SILVerifier.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4814,7 +4814,6 @@ void SILProperty::verify(const SILModule &M) const {
48144814

48154815
auto *decl = getDecl();
48164816
auto *dc = decl->getInnermostDeclContext();
4817-
auto &component = getComponent();
48184817

48194818
// TODO: base type for global/static descriptors
48204819
auto sig = dc->getGenericSignatureOfContext();
@@ -4844,21 +4843,22 @@ void SILProperty::verify(const SILModule &M) const {
48444843
}
48454844
};
48464845

4847-
verifyKeyPathComponent(const_cast<SILModule&>(M),
4848-
require,
4849-
baseTy,
4850-
leafTy,
4851-
component,
4852-
{},
4853-
canSig,
4854-
subs,
4855-
/*property descriptor*/true,
4856-
hasIndices);
4857-
4858-
// verifyKeyPathComponent updates baseTy to be the projected type of the
4859-
// component, which should be the same as the type of the declared storage
4860-
require(baseTy == leafTy,
4861-
"component type of property descriptor should match type of storage");
4846+
if (auto &component = getComponent()) {
4847+
verifyKeyPathComponent(const_cast<SILModule&>(M),
4848+
require,
4849+
baseTy,
4850+
leafTy,
4851+
*component,
4852+
{},
4853+
canSig,
4854+
subs,
4855+
/*property descriptor*/true,
4856+
hasIndices);
4857+
// verifyKeyPathComponent updates baseTy to be the projected type of the
4858+
// component, which should be the same as the type of the declared storage
4859+
require(baseTy == leafTy,
4860+
"component type of property descriptor should match type of storage");
4861+
}
48624862
}
48634863

48644864
/// Verify that a vtable follows invariants.

0 commit comments

Comments
 (0)