Skip to content

Commit e3bc23c

Browse files
authored
Merge pull request #8253 from swiftix/wip-gsb-layout-constrains-fixes
[GSB] Improve handling of layout constraints
2 parents 7a1a41f + e1403c6 commit e3bc23c

File tree

10 files changed

+336
-14
lines changed

10 files changed

+336
-14
lines changed

include/swift/AST/LayoutConstraint.h

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,16 @@ enum class LayoutConstraintKind : unsigned char {
4040
TrivialOfAtMostSize,
4141
// It is a layout constraint representing a trivial type of an unknown size.
4242
Trivial,
43+
// It is a layout constraint representing a reference counted class instance.
44+
Class,
45+
// It is a layout constraint representing a reference counted native class
46+
// instance.
47+
NativeClass,
4348
// It is a layout constraint representing a reference counted object.
4449
RefCountedObject,
4550
// It is a layout constraint representing a native reference counted object.
4651
NativeRefCountedObject,
52+
LastLayout = NativeRefCountedObject,
4753
};
4854

4955
/// This is a class representing the layout constraint.
@@ -108,6 +114,22 @@ class LayoutConstraintInfo : public llvm::FoldingSetNode {
108114
return isNativeRefCountedObject(Kind);
109115
}
110116

117+
bool isClass() const {
118+
return isClass(Kind);
119+
}
120+
121+
bool isNativeClass() const {
122+
return isNativeClass(Kind);
123+
}
124+
125+
bool isRefCounted() const {
126+
return isRefCounted(Kind);
127+
}
128+
129+
bool isNativeRefCounted() const {
130+
return isNativeRefCounted(Kind);
131+
}
132+
111133
unsigned getTrivialSizeInBytes() const {
112134
assert(isKnownSizeTrivial());
113135
return (SizeInBits + 7) / 8;
@@ -170,6 +192,16 @@ class LayoutConstraintInfo : public llvm::FoldingSetNode {
170192

171193
static bool isNativeRefCountedObject(LayoutConstraintKind Kind);
172194

195+
static bool isAnyRefCountedObject(LayoutConstraintKind Kind);
196+
197+
static bool isClass(LayoutConstraintKind Kind);
198+
199+
static bool isNativeClass(LayoutConstraintKind Kind);
200+
201+
static bool isRefCounted(LayoutConstraintKind Kind);
202+
203+
static bool isNativeRefCounted(LayoutConstraintKind Kind);
204+
173205
/// Uniquing for the LayoutConstraintInfo.
174206
void Profile(llvm::FoldingSetNodeID &ID) {
175207
Profile(ID, Kind, SizeInBits, Alignment);
@@ -189,6 +221,14 @@ class LayoutConstraintInfo : public llvm::FoldingSetNode {
189221
void *operator new(size_t bytes, const ASTContext &ctx,
190222
AllocationArena arena, unsigned alignment = 8);
191223
void *operator new(size_t Bytes, void *Mem) throw() { return Mem; }
224+
225+
// Representation of the non-parametrized layouts.
226+
static LayoutConstraintInfo UnknownLayoutConstraintInfo;
227+
static LayoutConstraintInfo RefCountedObjectConstraintInfo;
228+
static LayoutConstraintInfo NativeRefCountedObjectConstraintInfo;
229+
static LayoutConstraintInfo ClassConstraintInfo;
230+
static LayoutConstraintInfo NativeClassConstraintInfo;
231+
static LayoutConstraintInfo TrivialConstraintInfo;
192232
};
193233

194234
/// A wrapper class containing a reference to the actual LayoutConstraintInfo
@@ -204,19 +244,25 @@ class LayoutConstraint {
204244
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind,
205245
ASTContext &C);
206246

247+
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind);
248+
207249
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind,
208250
unsigned SizeInBits,
209251
unsigned Alignment,
210252
ASTContext &C);
211253

212-
static LayoutConstraint getUnknownLayout(ASTContext &C);
254+
static LayoutConstraint getUnknownLayout();
213255

214256
LayoutConstraintInfo *getPointer() const { return Ptr; }
215257

216258
bool isNull() const { return Ptr == 0; }
217259

218260
LayoutConstraintInfo *operator->() const { return Ptr; }
219261

262+
/// Merge these two constraints and return a more specific one
263+
/// or fail if they’re incompatible and return an unknown constraint.
264+
LayoutConstraint merge(LayoutConstraint Other);
265+
220266
explicit operator bool() const { return Ptr != 0; }
221267

222268
void dump() const;

lib/AST/ASTContext.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4074,6 +4074,12 @@ LayoutConstraint LayoutConstraint::getLayoutConstraint(LayoutConstraintKind Kind
40744074
unsigned SizeInBits,
40754075
unsigned Alignment,
40764076
ASTContext &C) {
4077+
if (!LayoutConstraintInfo::isKnownSizeTrivial(Kind)) {
4078+
assert(SizeInBits == 0);
4079+
assert(Alignment == 0);
4080+
return getLayoutConstraint(Kind);
4081+
}
4082+
40774083
// Check to see if we've already seen this tuple before.
40784084
llvm::FoldingSetNodeID ID;
40794085
LayoutConstraintInfo::Profile(ID, Kind, SizeInBits, Alignment);
@@ -4094,7 +4100,4 @@ LayoutConstraint LayoutConstraint::getLayoutConstraint(LayoutConstraintKind Kind
40944100
return LayoutConstraint(New);
40954101
}
40964102

4097-
LayoutConstraint LayoutConstraint::getUnknownLayout(ASTContext &C) {
4098-
return getLayoutConstraint(LayoutConstraintKind::UnknownLayout, 0, 0, C);
4099-
}
41004103

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2080,9 +2080,14 @@ bool GenericSignatureBuilder::addLayoutRequirement(
20802080
equivClass->layoutConstraints.push_back({PAT, Layout, Source});
20812081

20822082
// Update the layout in the equivalence class, if we didn't have one already.
2083-
// FIXME: Layouts can probably be merged sensibly.
20842083
if (!equivClass->layout)
20852084
equivClass->layout = Layout;
2085+
else {
2086+
// Try to merge layout constraints.
2087+
auto mergedLayout = equivClass->layout.merge(Layout);
2088+
if (mergedLayout->isKnownLayout() && mergedLayout != equivClass->layout)
2089+
equivClass->layout = mergedLayout;
2090+
}
20862091

20872092
return false;
20882093
}
@@ -2121,6 +2126,16 @@ bool GenericSignatureBuilder::updateSuperclass(
21212126
if (!equivClass->superclass) {
21222127
equivClass->superclass = superclass;
21232128
updateSuperclassConformances();
2129+
// Presence of a superclass constraint implies a _Class layout
2130+
// constraint.
2131+
auto layoutReqSource = source->viaSuperclass(*this, nullptr);
2132+
addLayoutRequirement(T,
2133+
LayoutConstraint::getLayoutConstraint(
2134+
superclass->getClassOrBoundGenericClass()->isObjC()
2135+
? LayoutConstraintKind::Class
2136+
: LayoutConstraintKind::NativeClass,
2137+
getASTContext()),
2138+
layoutReqSource);
21242139
return false;
21252140
}
21262141

@@ -3781,7 +3796,9 @@ void GenericSignatureBuilder::checkLayoutConstraints(
37813796
return constraint.value == equivClass->layout;
37823797
},
37833798
[&](LayoutConstraint layout) {
3784-
if (layout == equivClass->layout)
3799+
// If the layout constraints are mergable, i.e. compatible,
3800+
// it is a redundancy.
3801+
if (layout.merge(equivClass->layout)->isKnownLayout())
37853802
return ConstraintRelation::Redundant;
37863803

37873804
return ConstraintRelation::Conflicting;

0 commit comments

Comments
 (0)