Skip to content

Commit 1e46f13

Browse files
authored
Merge pull request #7321 from swiftix/layout-constraint-fixes
Layout constraint fixes
2 parents c98e515 + e5d5d7d commit 1e46f13

File tree

8 files changed

+172
-52
lines changed

8 files changed

+172
-52
lines changed

include/swift/AST/LayoutConstraint.h

Lines changed: 52 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/AST/TypeAlignments.h"
2121
#include "swift/Basic/SourceLoc.h"
2222
#include "llvm/ADT/DenseMap.h"
23+
#include "llvm/ADT/FoldingSet.h"
2324
#include "llvm/ADT/StringRef.h"
2425
#include "swift/AST/PrintOptions.h"
2526

@@ -46,15 +47,15 @@ enum class LayoutConstraintKind : unsigned char {
4647
};
4748

4849
/// This is a class representing the layout constraint.
49-
class LayoutConstraintInfo {
50+
class LayoutConstraintInfo : public llvm::FoldingSetNode {
51+
friend class LayoutConstraint;
5052
// Alignment of the layout in bytes.
51-
unsigned Alignment : 16;
53+
const unsigned Alignment : 16;
5254
// Size of the layout in bits.
53-
unsigned SizeInBits : 24;
55+
const unsigned SizeInBits : 24;
5456
// Kind of the layout.
55-
LayoutConstraintKind Kind;
57+
const LayoutConstraintKind Kind;
5658

57-
public:
5859
LayoutConstraintInfo()
5960
: Alignment(0), SizeInBits(0), Kind(LayoutConstraintKind::UnknownLayout) {
6061
}
@@ -73,44 +74,38 @@ class LayoutConstraintInfo {
7374
unsigned Alignment)
7475
: Alignment(Alignment), SizeInBits(SizeInBits), Kind(Kind) {
7576
assert(
76-
isKnownSizeTrivial() &&
77+
isTrivial() &&
7778
"Size in bits should be specified only for trivial layout constraints");
7879
}
79-
80-
static LayoutConstraintInfo getUnknownLayout() {
81-
return LayoutConstraintInfo(LayoutConstraintKind::UnknownLayout);
82-
}
83-
80+
public:
8481
LayoutConstraintKind getKind() const { return Kind; }
8582

8683
bool isKnownLayout() const {
87-
return Kind != LayoutConstraintKind::UnknownLayout;
84+
return isKnownLayout(Kind);
8885
}
8986

9087
bool isFixedSizeTrivial() const {
91-
return Kind == LayoutConstraintKind::TrivialOfExactSize;
88+
return isFixedSizeTrivial(Kind);
9289
}
9390

9491
bool isKnownSizeTrivial() const {
95-
return Kind > LayoutConstraintKind::UnknownLayout &&
96-
Kind < LayoutConstraintKind::Trivial;
92+
return isKnownSizeTrivial(Kind);
9793
}
9894

9995
bool isAddressOnlyTrivial() const {
100-
return Kind == LayoutConstraintKind::Trivial;
96+
return isAddressOnlyTrivial(Kind);
10197
}
10298

10399
bool isTrivial() const {
104-
return Kind > LayoutConstraintKind::UnknownLayout &&
105-
Kind <= LayoutConstraintKind::Trivial;
100+
return isTrivial(Kind);
106101
}
107102

108103
bool isRefCountedObject() const {
109-
return Kind == LayoutConstraintKind::RefCountedObject;
104+
return isRefCountedObject(Kind);
110105
}
111106

112107
bool isNativeRefCountedObject() const {
113-
return Kind == LayoutConstraintKind::NativeRefCountedObject;
108+
return isNativeRefCountedObject(Kind);
114109
}
115110

116111
unsigned getTrivialSizeInBytes() const {
@@ -161,6 +156,29 @@ class LayoutConstraintInfo {
161156
/// Return the name of a layout constraint with a given kind.
162157
static StringRef getName(LayoutConstraintKind Kind);
163158

159+
static bool isKnownLayout(LayoutConstraintKind Kind);
160+
161+
static bool isFixedSizeTrivial(LayoutConstraintKind Kind);
162+
163+
static bool isKnownSizeTrivial(LayoutConstraintKind Kind);
164+
165+
static bool isAddressOnlyTrivial(LayoutConstraintKind Kind);
166+
167+
static bool isTrivial(LayoutConstraintKind Kind);
168+
169+
static bool isRefCountedObject(LayoutConstraintKind Kind);
170+
171+
static bool isNativeRefCountedObject(LayoutConstraintKind Kind);
172+
173+
/// Uniquing for the LayoutConstraintInfo.
174+
void Profile(llvm::FoldingSetNodeID &ID) {
175+
Profile(ID, Kind, SizeInBits, Alignment);
176+
}
177+
178+
static void Profile(llvm::FoldingSetNodeID &ID,
179+
LayoutConstraintKind Kind,
180+
unsigned SizeInBits,
181+
unsigned Alignment);
164182
private:
165183
// Make vanilla new/delete illegal for LayoutConstraintInfo.
166184
void *operator new(size_t Bytes) throw() = delete;
@@ -180,6 +198,19 @@ class LayoutConstraint {
180198
public:
181199
/*implicit*/ LayoutConstraint(LayoutConstraintInfo *P = 0) : Ptr(P) {}
182200

201+
static LayoutConstraint getLayoutConstraint(const LayoutConstraint &Layout,
202+
ASTContext &C);
203+
204+
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind,
205+
ASTContext &C);
206+
207+
static LayoutConstraint getLayoutConstraint(LayoutConstraintKind Kind,
208+
unsigned SizeInBits,
209+
unsigned Alignment,
210+
ASTContext &C);
211+
212+
static LayoutConstraint getUnknownLayout(ASTContext &C);
213+
183214
LayoutConstraintInfo *getPointer() const { return Ptr; }
184215

185216
bool isNull() const { return Ptr == 0; }
@@ -258,7 +289,7 @@ struct LayoutConstraintLoc {
258289
/// Checks if ID is a name of a layout constraint and returns this
259290
/// constraint. If ID does not match any known layout constraint names,
260291
/// returns UnknownLayout.
261-
LayoutConstraintInfo getLayoutConstraintInfo(Identifier ID, ASTContext &Ctx);
292+
LayoutConstraint getLayoutConstraint(Identifier ID, ASTContext &Ctx);
262293

263294
} // end namespace swift
264295

include/swift/Parse/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,7 @@ class Parser {
869869
bool HandleCodeCompletion = true);
870870

871871
/// \brief Parse layout constraint.
872-
LayoutConstraintInfo parseLayoutConstraint(Identifier LayoutConstraintID);
872+
LayoutConstraint parseLayoutConstraint(Identifier LayoutConstraintID);
873873

874874
bool parseGenericArguments(SmallVectorImpl<TypeRepr*> &Args,
875875
SourceLoc &LAngleLoc,

lib/AST/ASTContext.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ struct ASTContext::Implementation {
259259
llvm::FoldingSet<UnboundGenericType> UnboundGenericTypes;
260260
llvm::FoldingSet<BoundGenericType> BoundGenericTypes;
261261
llvm::FoldingSet<ProtocolType> ProtocolTypes;
262+
llvm::FoldingSet<LayoutConstraintInfo> LayoutConstraints;
262263

263264
llvm::DenseMap<std::pair<TypeBase *, DeclContext *>,
264265
SubstitutionList>
@@ -4060,4 +4061,37 @@ CanSILBoxType SILBoxType::get(CanType boxedType) {
40604061
return get(boxedType->getASTContext(), layout, Substitution(boxedType, {}));
40614062
}
40624063

4064+
LayoutConstraint
4065+
LayoutConstraint::getLayoutConstraint(LayoutConstraintKind Kind,
4066+
ASTContext &C) {
4067+
return getLayoutConstraint(Kind, 0, 0, C);
4068+
}
4069+
4070+
LayoutConstraint LayoutConstraint::getLayoutConstraint(LayoutConstraintKind Kind,
4071+
unsigned SizeInBits,
4072+
unsigned Alignment,
4073+
ASTContext &C) {
4074+
// Check to see if we've already seen this tuple before.
4075+
llvm::FoldingSetNodeID ID;
4076+
LayoutConstraintInfo::Profile(ID, Kind, SizeInBits, Alignment);
4077+
4078+
void *InsertPos = nullptr;
4079+
if (LayoutConstraintInfo *Layout =
4080+
C.Impl.getArena(AllocationArena::Permanent)
4081+
.LayoutConstraints.FindNodeOrInsertPos(ID, InsertPos))
4082+
return LayoutConstraint(Layout);
4083+
4084+
LayoutConstraintInfo *New =
4085+
LayoutConstraintInfo::isTrivial(Kind)
4086+
? new (C, AllocationArena::Permanent)
4087+
LayoutConstraintInfo(Kind, SizeInBits, Alignment)
4088+
: new (C, AllocationArena::Permanent) LayoutConstraintInfo(Kind);
4089+
C.Impl.getArena(AllocationArena::Permanent)
4090+
.LayoutConstraints.InsertNode(New, InsertPos);
4091+
return LayoutConstraint(New);
4092+
}
4093+
4094+
LayoutConstraint LayoutConstraint::getUnknownLayout(ASTContext &C) {
4095+
return getLayoutConstraint(LayoutConstraintKind::UnknownLayout, 0, 0, C);
4096+
}
40634097

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4121,7 +4121,10 @@ void Requirement::dump() const {
41214121
}
41224122

41234123
if (getFirstType()) llvm::errs() << getFirstType() << " ";
4124-
if (getSecondType()) llvm::errs() << getSecondType();
4124+
if (getKind() != RequirementKind::Layout && getSecondType())
4125+
llvm::errs() << getSecondType();
4126+
else if (getLayoutConstraint())
4127+
llvm::errs() << getLayoutConstraint();
41254128
llvm::errs() << "\n";
41264129
}
41274130

lib/AST/LayoutConstraint.cpp

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,25 @@ namespace swift {
2222

2323
/// This helper function is typically used by the parser to
2424
/// map a type name to a corresponding layout constraint if possible.
25-
LayoutConstraintInfo getLayoutConstraintInfo(Identifier ID, ASTContext &Ctx) {
25+
LayoutConstraint getLayoutConstraint(Identifier ID, ASTContext &Ctx) {
2626
if (ID == Ctx.Id_TrivialLayout)
27-
return LayoutConstraintInfo(LayoutConstraintKind::TrivialOfExactSize, 0, 0);
27+
return LayoutConstraint::getLayoutConstraint(
28+
LayoutConstraintKind::TrivialOfExactSize, 0, 0, Ctx);
2829

2930
if (ID == Ctx.Id_TrivialAtMostLayout)
30-
return LayoutConstraintInfo(LayoutConstraintKind::TrivialOfAtMostSize, 0,
31-
0);
31+
return LayoutConstraint::getLayoutConstraint(
32+
LayoutConstraintKind::TrivialOfAtMostSize, 0, 0, Ctx);
3233

3334
if (ID == Ctx.Id_RefCountedObjectLayout)
34-
return LayoutConstraintInfo(LayoutConstraintKind::RefCountedObject);
35+
return LayoutConstraint::getLayoutConstraint(
36+
LayoutConstraintKind::RefCountedObject, Ctx);
3537

3638
if (ID == Ctx.Id_NativeRefCountedObjectLayout)
37-
return LayoutConstraintInfo(LayoutConstraintKind::NativeRefCountedObject);
39+
return LayoutConstraint::getLayoutConstraint(
40+
LayoutConstraintKind::NativeRefCountedObject, Ctx);
3841

39-
return LayoutConstraintInfo(LayoutConstraintKind::UnknownLayout);
42+
return LayoutConstraint::getLayoutConstraint(
43+
LayoutConstraintKind::UnknownLayout, Ctx);
4044
}
4145

4246
StringRef LayoutConstraintInfo::getName() const {
@@ -62,6 +66,52 @@ StringRef LayoutConstraintInfo::getName(LayoutConstraintKind Kind) {
6266
llvm_unreachable("Unhandled LayoutConstraintKind in switch.");
6367
}
6468

69+
/// Uniquing for the LayoutConstraintInfo.
70+
void LayoutConstraintInfo::Profile(llvm::FoldingSetNodeID &ID,
71+
LayoutConstraintKind Kind,
72+
unsigned SizeInBits,
73+
unsigned Alignment) {
74+
ID.AddInteger((unsigned)Kind);
75+
ID.AddInteger(SizeInBits);
76+
ID.AddInteger(Alignment);
77+
}
78+
79+
bool LayoutConstraintInfo::isKnownLayout(LayoutConstraintKind Kind) {
80+
return Kind != LayoutConstraintKind::UnknownLayout;
81+
}
82+
83+
bool LayoutConstraintInfo::isFixedSizeTrivial(LayoutConstraintKind Kind) {
84+
return Kind == LayoutConstraintKind::TrivialOfExactSize;
85+
}
86+
87+
bool LayoutConstraintInfo::isKnownSizeTrivial(LayoutConstraintKind Kind) {
88+
return Kind > LayoutConstraintKind::UnknownLayout &&
89+
Kind < LayoutConstraintKind::Trivial;
90+
}
91+
92+
bool LayoutConstraintInfo::isAddressOnlyTrivial(LayoutConstraintKind Kind) {
93+
return Kind == LayoutConstraintKind::Trivial;
94+
}
95+
96+
bool LayoutConstraintInfo::isTrivial(LayoutConstraintKind Kind) {
97+
return Kind > LayoutConstraintKind::UnknownLayout &&
98+
Kind <= LayoutConstraintKind::Trivial;
99+
}
100+
101+
bool LayoutConstraintInfo::isRefCountedObject(LayoutConstraintKind Kind) {
102+
return Kind == LayoutConstraintKind::RefCountedObject;
103+
}
104+
105+
bool LayoutConstraintInfo::isNativeRefCountedObject(LayoutConstraintKind Kind) {
106+
return Kind == LayoutConstraintKind::NativeRefCountedObject;
107+
}
108+
109+
void *LayoutConstraintInfo::operator new(size_t bytes, const ASTContext &ctx,
110+
AllocationArena arena,
111+
unsigned alignment) {
112+
return ctx.Allocate(bytes, alignment, arena);
113+
}
114+
65115
SourceRange LayoutConstraintLoc::getSourceRange() const { return getLoc(); }
66116

67117
} // end namespace swift

lib/Parse/ParseGeneric.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,18 +258,19 @@ ParserStatus Parser::parseGenericWhereClause(
258258
SourceLoc ColonLoc = consumeToken();
259259

260260
if (Tok.is(tok::identifier) &&
261-
getLayoutConstraintInfo(Context.getIdentifier(Tok.getText()),
262-
Context)) {
261+
getLayoutConstraint(Context.getIdentifier(Tok.getText()), Context)
262+
->isKnownLayout()) {
263263
// Parse a layout constraint.
264264
auto LayoutName = Context.getIdentifier(Tok.getText());
265265
auto LayoutLoc = consumeToken();
266266
auto LayoutInfo = parseLayoutConstraint(LayoutName);
267-
if (!LayoutInfo.isKnownLayout()) {
267+
if (!LayoutInfo->isKnownLayout()) {
268268
// There was a bug in the layout constraint.
269269
Status.setIsParseError();
270270
}
271-
auto Layout = LayoutConstraint(Context.AllocateObjectCopy(LayoutInfo));
272-
if (!AllowLayoutConstraints) {
271+
auto Layout = LayoutInfo;
272+
// Types in SIL mode may contain layout constraints.
273+
if (!AllowLayoutConstraints && !isInSILMode()) {
273274
diagnose(LayoutLoc,
274275
diag::layout_constraints_only_inside_specialize_attr);
275276
} else {

lib/Parse/ParseType.cpp

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,20 +59,20 @@ TypeRepr *Parser::applyAttributeToType(TypeRepr *ty,
5959
return ty;
6060
}
6161

62-
LayoutConstraintInfo
63-
Parser::parseLayoutConstraint(Identifier LayoutConstraintID) {
64-
LayoutConstraintInfo layoutConstraint =
65-
getLayoutConstraintInfo(LayoutConstraintID, Context);
66-
assert(layoutConstraint.isKnownLayout() &&
62+
LayoutConstraint Parser::parseLayoutConstraint(Identifier LayoutConstraintID) {
63+
LayoutConstraint layoutConstraint =
64+
getLayoutConstraint(LayoutConstraintID, Context);
65+
assert(layoutConstraint->isKnownLayout() &&
6766
"Expected layout constraint definition");
6867

69-
if (!layoutConstraint.isTrivial())
68+
if (!layoutConstraint->isTrivial())
7069
return layoutConstraint;
7170

7271
SourceLoc LParenLoc;
7372
if (!consumeIf(tok::l_paren, LParenLoc)) {
7473
// It is a trivial without any size constraints.
75-
return LayoutConstraintInfo(LayoutConstraintKind::Trivial);
74+
return LayoutConstraint::getLayoutConstraint(LayoutConstraintKind::Trivial,
75+
Context);
7676
}
7777

7878
int size = 0;
@@ -110,29 +110,30 @@ Parser::parseLayoutConstraint(Identifier LayoutConstraintID) {
110110
// There was an error during parsing.
111111
skipUntil(tok::r_paren);
112112
consumeIf(tok::r_paren);
113-
return LayoutConstraintInfo::getUnknownLayout();
113+
return LayoutConstraint::getUnknownLayout(Context);
114114
}
115115

116116
if (!consumeIf(tok::r_paren)) {
117117
// Expected a closing r_paren.
118118
diagnose(Tok.getLoc(), diag::expected_rparen_layout_constraint);
119119
consumeToken();
120-
return LayoutConstraintInfo::getUnknownLayout();
120+
return LayoutConstraint::getUnknownLayout(Context);
121121
}
122122

123123
if (size < 0) {
124124
diagnose(Tok.getLoc(), diag::layout_size_should_be_positive);
125-
return LayoutConstraintInfo::getUnknownLayout();
125+
return LayoutConstraint::getUnknownLayout(Context);
126126
}
127127

128128
if (alignment < 0) {
129129
diagnose(Tok.getLoc(), diag::layout_alignment_should_be_positive);
130-
return LayoutConstraintInfo::getUnknownLayout();
130+
return LayoutConstraint::getUnknownLayout(Context);
131131
}
132132

133133
// Otherwise it is a trivial layout constraint with
134134
// provided size and alignment.
135-
return LayoutConstraintInfo(layoutConstraint.getKind(), size, alignment);
135+
return LayoutConstraint::getLayoutConstraint(layoutConstraint->getKind(), size,
136+
alignment, Context);
136137
}
137138

138139
ParserResult<TypeRepr> Parser::parseTypeSimple() {

0 commit comments

Comments
 (0)