@@ -140,6 +140,168 @@ void *LayoutConstraintInfo::operator new(size_t bytes, const ASTContext &ctx,
140
140
141
141
SourceRange LayoutConstraintLoc::getSourceRange () const { return getLoc (); }
142
142
143
+ #define MERGE_LOOKUP (lhs, rhs ) \
144
+ mergeTable[int (lhs)][int (rhs)]
145
+
146
+ // Shortcut for spelling the whole enumerator.
147
+ #define E (X ) LayoutConstraintKind::X
148
+ #define MERGE_CONFLICT LayoutConstraintKind::UnknownLayout
149
+
150
+ // / This is a 2-D table defining the merging rules for layout constraints.
151
+ // / It is indexed by means of LayoutConstraintKind.
152
+ // / mergeTable[i][j] tells the kind of a layout constraint is the result
153
+ // / of merging layout constraints of kinds 'i' and 'j'.
154
+ // /
155
+ // / Some of the properties of the merge table, where C is any type of layout
156
+ // / constraint:
157
+ // / UnknownLayout x C -> C
158
+ // / C x UnknownLayout -> C
159
+ // / C x C -> C
160
+ // / mergeTable[i][j] == mergeTable[j][i], i.e. the table is symmetric.
161
+ // / mergeTable[i][j] == UnknownLayout if merging layout constraints of kinds i
162
+ // / and j would result in a conflict.
163
+ static LayoutConstraintKind mergeTable[unsigned (E(LastLayout)) +
164
+ 1 ][unsigned (E(LastLayout)) + 1 ] = {
165
+ // Initialize the row for UnknownLayout.
166
+ {E (/* UnknownLayout */ UnknownLayout),
167
+ E (/* TrivialOfExactSize */ TrivialOfExactSize),
168
+ E (/* TrivialOfAtMostSize */ TrivialOfAtMostSize), E (/* Trivial */ Trivial),
169
+ E (/* Class */ Class), E (/* NativeClass */ NativeClass),
170
+ E (/* RefCountedObject*/ RefCountedObject),
171
+ E (/* NativeRefCountedObject */ NativeRefCountedObject)},
172
+
173
+ // Initiaze the row for TrivialOfExactSize.
174
+ {E (/* UnknownLayout */ TrivialOfExactSize),
175
+ E (/* TrivialOfExactSize */ TrivialOfExactSize), MERGE_CONFLICT,
176
+ E (/* Trivial */ TrivialOfExactSize), MERGE_CONFLICT, MERGE_CONFLICT,
177
+ MERGE_CONFLICT, MERGE_CONFLICT},
178
+
179
+ // Initiaze the row for TrivialOfAtMostSize.
180
+ {E (/* UnknownLayout */ TrivialOfAtMostSize), MERGE_CONFLICT,
181
+ E (/* TrivialOfAtMostSize */ TrivialOfAtMostSize),
182
+ E (/* Trivial */ TrivialOfAtMostSize), MERGE_CONFLICT, MERGE_CONFLICT,
183
+ MERGE_CONFLICT, MERGE_CONFLICT},
184
+
185
+ // Initiaze the row for Trivial.
186
+ {E (/* UnknownLayout */ Trivial),
187
+ E (/* TrivialOfExactSize */ TrivialOfExactSize),
188
+ E (/* TrivialOfAtMostSize */ TrivialOfAtMostSize), E (/* Trivial */ Trivial),
189
+ MERGE_CONFLICT, MERGE_CONFLICT, MERGE_CONFLICT, MERGE_CONFLICT},
190
+
191
+ // Initiaze the row for Class.
192
+ {E (/* UnknownLayout*/ Class), MERGE_CONFLICT, MERGE_CONFLICT,
193
+ MERGE_CONFLICT, E (/* Class */ Class), E (/* NativeClass */ NativeClass),
194
+ E (/* RefCountedObject */ Class),
195
+ E (/* NativeRefCountedObject */ NativeClass)},
196
+
197
+ // Initiaze the row for NativeClass.
198
+ {E (/* UnknownLayout */ NativeClass), MERGE_CONFLICT, MERGE_CONFLICT,
199
+ MERGE_CONFLICT, E (/* Class */ NativeClass),
200
+ E (/* NativeClass */ NativeClass), E (/* RefCountedObject */ NativeClass),
201
+ E (/* NativeRefCountedObject */ NativeClass)},
202
+
203
+ // Initiaze the row for RefCountedObject.
204
+ {E (/* UnknownLayout */ RefCountedObject), MERGE_CONFLICT, MERGE_CONFLICT,
205
+ MERGE_CONFLICT, E (/* Class */ Class), E (/* NativeClass */ NativeClass),
206
+ E (/* RefCountedObject */ RefCountedObject),
207
+ E (/* NativeRefCountedObject */ NativeRefCountedObject)},
208
+
209
+ // Initiaze the row for NativeRefCountedObject.
210
+ {E (/* UnknownLayout */ NativeRefCountedObject), MERGE_CONFLICT,
211
+ MERGE_CONFLICT, MERGE_CONFLICT, E (/* Class */ NativeClass),
212
+ E (/* NativeClass */ NativeClass),
213
+ E (/* RefCountedObject */ NativeRefCountedObject),
214
+ E (/* NativeRefCountedObject*/ NativeRefCountedObject)},
215
+ };
216
+
217
+ #undef E
218
+
219
+ // Fixed-size trivial constraint can be combined with AtMostSize trivial
220
+ // constraint into a fixed-size trivial constraint, if
221
+ // fixed_size_layout.size <= at_most_size_layout.size and
222
+ // their alignment requirements are not contradicting.
223
+ //
224
+ // Only merges if LHS would become the result of the merge.
225
+ static LayoutConstraint
226
+ mergeKnownSizeTrivialConstraints (LayoutConstraint LHS, LayoutConstraint RHS) {
227
+ assert (LHS->isKnownSizeTrivial () && RHS->isKnownSizeTrivial ());
228
+
229
+ // LHS should be fixed-size.
230
+ if (!LHS->isFixedSizeTrivial ())
231
+ return LayoutConstraint::getUnknownLayout ();
232
+
233
+ // RHS should be at-most-size.
234
+ if (RHS->isFixedSizeTrivial ())
235
+ return LayoutConstraint::getUnknownLayout ();
236
+
237
+ // Check that sizes are compatible, i.e.
238
+ // fixed_size_layout.size <= at_most_size_layout.size
239
+ if (LHS->getMaxTrivialSizeInBits () > RHS->getMaxTrivialSizeInBits ())
240
+ return LayoutConstraint::getUnknownLayout ();
241
+
242
+ // Check alignments
243
+
244
+ // Quick exit if at_most_size_layout does not care about the alignment.
245
+ if (!RHS->getAlignment ())
246
+ return LHS;
247
+
248
+ // Check if fixed_size_layout.alignment is a multple of
249
+ // at_most_size_layout.alignment.
250
+ if (LHS->getAlignment () && LHS->getAlignment () % RHS->getAlignment () == 0 )
251
+ return LHS;
252
+
253
+ return LayoutConstraint::getUnknownLayout ();
254
+ }
255
+
256
+ LayoutConstraint
257
+ LayoutConstraint::merge (LayoutConstraint Other) {
258
+ auto Self = *this ;
259
+
260
+ // If both constraints are the same, they are always equal.
261
+ if (Self == Other)
262
+ return Self;
263
+
264
+ // TrivialOfExactSize and TrivialOfAtMostSize are a special case,
265
+ // because not only their kind, but their parameters need to be compared as
266
+ // well.
267
+ if (Self->isKnownSizeTrivial () && Other->isKnownSizeTrivial ()) {
268
+ // If we got here, it means that the Self == Other check above has failed.
269
+ // And that could only happen if either the kinds are different or
270
+ // size/alignment parameters are different.
271
+
272
+ // Try to merge fixed-size constraint with an at-most-size constraint,
273
+ // if possible.
274
+ LayoutConstraint MergedKnownSizeTrivial;
275
+ MergedKnownSizeTrivial = mergeKnownSizeTrivialConstraints (Self, Other);
276
+ if (MergedKnownSizeTrivial->isKnownLayout ())
277
+ return MergedKnownSizeTrivial;
278
+
279
+ MergedKnownSizeTrivial = mergeKnownSizeTrivialConstraints (Other, Self);
280
+ if (MergedKnownSizeTrivial->isKnownLayout ())
281
+ return MergedKnownSizeTrivial;
282
+
283
+ return LayoutConstraint::getUnknownLayout ();
284
+ }
285
+
286
+ // Lookup in the mergeTable if this combination of layouts can be merged.
287
+ auto mergeKind = MERGE_LOOKUP (Self->getKind (), Other->getKind ());
288
+ // The merge table should be symmetric.
289
+ assert (mergeKind == MERGE_LOOKUP (Other->getKind (), Self->getKind ()));
290
+
291
+ // Merge is not possible, report a conflict.
292
+ if (mergeKind == LayoutConstraintKind::UnknownLayout)
293
+ return LayoutConstraint::getUnknownLayout ();
294
+
295
+ if (Self->getKind () == mergeKind)
296
+ return Self;
297
+
298
+ if (Other->getKind () == mergeKind)
299
+ return Other;
300
+
301
+ // The result of the merge is not equal to any of the input constraints, e.g.
302
+ // Class x NativeRefCountedObject -> NativeClass.
303
+ return LayoutConstraint::getLayoutConstraint (mergeKind);
304
+ }
143
305
144
306
LayoutConstraint
145
307
LayoutConstraint::getLayoutConstraint (LayoutConstraintKind Kind) {
0 commit comments