@@ -94,7 +94,7 @@ static bool TypeHasMayAlias(QualType QTy) {
94
94
}
95
95
96
96
// / Check if the given type is a valid base type to be used in access tags.
97
- static bool isValidBaseType (QualType QTy) {
97
+ static bool isValidBaseType (QualType QTy, const CodeGenOptions &CodeGenOpts ) {
98
98
if (QTy->isReferenceType ())
99
99
return false ;
100
100
if (const RecordType *TTy = QTy->getAs <RecordType>()) {
@@ -105,13 +105,154 @@ static bool isValidBaseType(QualType QTy) {
105
105
if (RD->hasFlexibleArrayMember ())
106
106
return false ;
107
107
// RD can be struct, union, class, interface or enum.
108
- // For now, we only handle struct and class.
109
- if (RD->isStruct () || RD-> isClass ( ))
108
+ if (RD-> isStruct () || RD-> isClass () ||
109
+ (RD->isUnion () && CodeGenOpts. UnionTBAA ))
110
110
return true ;
111
111
}
112
112
return false ;
113
113
}
114
114
115
+ // Appends unique tag for compatible pointee types.
116
+ void CodeGenTBAA::appendPointeeName (llvm::raw_ostream &OS, const Type *Ty) {
117
+ // Although type compatibilty in C standard requires cv-qualification
118
+ // match and exact type match, here more relaxed rules are applied.
119
+ //
120
+ // For built-in types consider them 'compatible' if their respective
121
+ // TBAA metadata tag is same(e.g. that makes 'int' and 'unsigned'
122
+ // compatible).
123
+ if (isa<BuiltinType>(Ty)) {
124
+ llvm::MDNode *ScalarMD = getTypeInfoHelper (Ty);
125
+ auto &Op = ScalarMD->getOperand (CodeGenOpts.NewStructPathTBAA ? 2 : 0 );
126
+ assert (isa<llvm::MDString>(Op) && " Expected MDString operand" );
127
+ OS << cast<llvm::MDString>(Op)->getString ().str ();
128
+ }
129
+
130
+ // Non-builtin types are considered compatible if their tag matches.
131
+ OS << Ty->getUnqualifiedDesugaredType ()
132
+ ->getCanonicalTypeInternal ()
133
+ .getAsString ();
134
+ }
135
+
136
+ // / Return an LLVM TBAA metadata node appropriate for an access through
137
+ // / an l-value of the given type. Type-based alias analysis takes advantage
138
+ // / of the following rules from the language standards:
139
+ // /
140
+ // / C 6.5p7:
141
+ // / An object shall have its stored value accessed only by an lvalue
142
+ // / expression that has one of the following types:
143
+ // / - a type compatible with the effective type of the object,
144
+ // / - a qualified version of a type compatible with the effective
145
+ // / type of the object,
146
+ // / - a type that is the signed or unsigned type corresponding
147
+ // / to the effective type of the object,
148
+ // / - a type that is the signed or unsigned type corresponding
149
+ // / to a qualified version of the effective type of the object,
150
+ // / - an aggregate or union type that includes one of the
151
+ // / aforementioned types among its members (including,
152
+ // / recursively, a member of a subaggregate or contained union), or
153
+ // / - a character type.
154
+ // /
155
+ // / C++ [basic.lval]p11:
156
+ // / If a program attempts to access the stored value of an object
157
+ // / through a glvalue whose type is not similar to one of the following
158
+ // / types the behavior is undefined:
159
+ // / - the dynamic type of the object,
160
+ // / - a type that is the signed or unsigned type corresponding
161
+ // / to the dynamic type of the object, or
162
+ // / - a char, unsigned char, or std::byte type.
163
+ // /
164
+ // / The C and C++ rules about effective/dynamic type are broadly similar
165
+ // / and permit memory to be reused with a different type. C does not have
166
+ // / an explicit operation to change the effective type of memory; any store
167
+ // / can do it. While C++ arguably does have such an operation (the standard
168
+ // / global `operator new(void*, size_t)`), in practice it is important to
169
+ // / be just as permissive as C. We therefore treat all stores as being able to
170
+ // / change the effective type of memory, regardless of language mode. That is,
171
+ // / loads have both a precondition and a postcondition on the effective
172
+ // / type of the memory, but stores only have a postcondition. This imposes
173
+ // / an inherent limitation that TBAA can only be used to reorder loads
174
+ // / before stores. This is quite restrictive, but we don't have much of a
175
+ // / choice. In practice, hoisting loads is the most important optimization
176
+ // / for alias analysis to enable anyway.
177
+ // /
178
+ // / Therefore, given a load (and its precondition) and an earlier store
179
+ // / (and its postcondition), the question posed to TBAA is whether there
180
+ // / exists a type that is consistent with both accesses. If there isn't,
181
+ // / it's fine to hoist the load because either the memory is non-overlapping
182
+ // / or the precondition on the load is wrong (which would be UB).
183
+ // /
184
+ // / LLVM TBAA says that two accesses with TBAA metadata nodes may alias if:
185
+ // / - the metadata nodes are the same,
186
+ // / - one of the metadata nodes is a base of the other (this can be
187
+ // / recursive, but it has to be the original node that's a base,
188
+ // / not just that the nodes have a common base), or
189
+ // / - one of the metadata nodes is a `tbaa.struct` node (the access
190
+ // / necessarily being a `memcpy`) with a subobject node that would
191
+ // / be allowed to alias with the other.
192
+ // /
193
+ // / Our job here is to produce metadata nodes that will never say that
194
+ // / an alias is not allowed when there exists a type that would be consistent
195
+ // / with the types of the accesses from which the nodes were produced.
196
+ // /
197
+ // / The last clause in both language rules permits character types to
198
+ // / alias objects of any type. We handle this by converting all character
199
+ // / types (as well as `std::byte` and types with the `mayalias` attribute)
200
+ // / to a single metadata node (the `char` node), then making sure that
201
+ // / that node is a base of every other metadata node we generate.
202
+ // / We can always just conservatively use this node if we aren't otherwise
203
+ // / sure how to implement the language rules for a type.
204
+ // /
205
+ // / Read literally, the C rule for aggregates permits an aggregate l-value
206
+ // / (e.g. of type `struct { int x; }`) to be used to access an object that
207
+ // / is not part of an aggregate object of that type (e.g. a local variable
208
+ // / of type `int`). That case is perhaps sensical, but it would also permit
209
+ // / e.g. an l-value of type `struct { int x; float f; }` to be used to
210
+ // / access an object of type `float`, which is nonsense. We interpret this
211
+ // / clause as just intending to permit objects to be accessed through an
212
+ // / l-value that properly references a containing object.
213
+ // /
214
+ // / C++ does not have an explicit rule for aggregates because in C++
215
+ // / a non-member access to an aggregate l-value is always a call to a
216
+ // / constructor or assignment operator, which then accesses all the
217
+ // / subobjects. In general, however, our interpretation of member
218
+ // / accesses is that they are also an access to the containing object
219
+ // / and therefore require such an object to exist at that address;
220
+ // / this permits us to just use the C rule for the accesses done by
221
+ // / trivial copy/move constructors/operators.
222
+ // /
223
+ // / Both C and C++ permit some qualification differences. In C, however,
224
+ // / qualification can only differ at the outermost level, whereas C++
225
+ // / allows qualification to differ in nested positions through the
226
+ // / similar-types rule. This means that e.g. an l-value of type
227
+ // / `const float *` is not permitted to access an object of type
228
+ // / `float *` in C, but it is in C++. We use the C++ rule
229
+ // / unconditionally; the C rule is needlessly strict and frequently
230
+ // / violated in practice by code that we don't want to say is wrong.
231
+ // / We implement this by just discarding type qualifiers within pointer-like
232
+ // / types when deriving TBAA nodes; basically, we produce the TBAA node
233
+ // / for the type that is unqualified at all the recursive positions
234
+ // / considered by the C++ similar type rule. The implementation
235
+ // / doesn't actually construct this recursively-qualified type as a
236
+ // / `QualType`; it just ignores qualifiers when recursing into types.
237
+ // /
238
+ // / The similar-type rule only really applies to the standard CVR
239
+ // / qualifiers, which never affect representations. Qualifiers such as
240
+ // / address spaces that may involve a representation difference would
241
+ // / be totally appropriate to distinguish for TBAA purposes. However,
242
+ // / the current implementation just discards all qualifiers.
243
+ // /
244
+ // / We handle the signed/unsigned clause by just making unsigned types
245
+ // / use the the metadata node for the signed variant of the type. In the
246
+ // / language rules, this only applies at the outermost level, and e.g. an
247
+ // / l-value of type `signed int *` is not permitted to alias an object of
248
+ // / type `unsigned int *`. We choose not to distinguish those types when
249
+ // / pointer-type TBAA is enabled, however.
250
+ // /
251
+ // / After discarding qualifiers and signedness differences as above,
252
+ // / the language rules come down to whether the types are compatible
253
+ // / (in C) or identical (in C++). Even in C, most types are compatible
254
+ // / only with themselves. The exceptions will be considered in the cases
255
+ // / below.
115
256
llvm::MDNode *CodeGenTBAA::getTypeInfoHelper (const Type *Ty) {
116
257
uint64_t Size = Context.getTypeSizeInChars (Ty).getQuantity ();
117
258
@@ -184,13 +325,40 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
184
325
return getChar ();
185
326
186
327
// Handle pointers and references.
187
- // TODO: Implement C++'s type "similarity" and consider dis-"similar"
188
- // pointers distinct.
189
- if (Ty->isPointerType () || Ty->isReferenceType ())
190
- return createScalarTypeNode (" any pointer" , getChar (), Size);
328
+ //
329
+ // When PointerTBAA is disabled, all pointers and references use the same
330
+ // "any pointer" TBAA node. Otherwise, we generate a type-specific TBAA
331
+ // node and use the "any pointer" node as its base for compatibility between
332
+ // TUs with different settings. To implement the C++ similar-type rules
333
+ // (which we also adopt in C), we need to ignore qualifiers on the
334
+ // pointee type, and that has to be done recursively if the pointee type
335
+ // is itself a pointer-like type.
336
+ //
337
+ // Currently we ignore the differences between pointer-like types and just
338
+ // and use this tag for the type: `p<pointer depth> <inner type tag>`.
339
+ // This means we give e.g. `char **` and `char A::**` the same TBAA tag.
340
+ if ((Ty->isPointerType () || Ty->isReferenceType ())) {
341
+ llvm::MDNode *AnyPtr = createScalarTypeNode (" any pointer" , getChar (), Size);
342
+ if (!CodeGenOpts.PointerTBAA )
343
+ return AnyPtr;
344
+ unsigned PtrDepth = 0 ;
345
+ do {
346
+ PtrDepth++;
347
+ Ty = Ty->getPointeeType ().getTypePtr ()->getUnqualifiedDesugaredType ();
348
+ // Any array-like type is considered a pointer-to qualification.
349
+ if (Ty && Ty->isArrayType ()) {
350
+ Ty = Ty->getAsArrayTypeUnsafe ()->getElementType ().getTypePtr ();
351
+ }
352
+ } while (!Ty->getPointeeType ().isNull ());
353
+ std::string PtrName;
354
+ llvm::raw_string_ostream OS{PtrName};
355
+ OS << " p" << PtrDepth << " " ;
356
+ appendPointeeName (OS, Ty);
357
+ return createScalarTypeNode (PtrName, AnyPtr, Size);
358
+ }
191
359
192
360
// Accesses to arrays are accesses to objects of their element types.
193
- if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType ())
361
+ if (CodeGenOpts.ArrayTBAA && Ty->isArrayType ())
194
362
return getTypeInfo (cast<ArrayType>(Ty)->getElementType ());
195
363
196
364
// Enum types are distinct types. In C++ they have "underlying types",
@@ -241,7 +409,7 @@ llvm::MDNode *CodeGenTBAA::getTypeInfo(QualType QTy) {
241
409
// subsequent accesses to direct and indirect members of that aggregate will
242
410
// be considered may-alias too.
243
411
// TODO: Combine getTypeInfo() and getBaseTypeInfo() into a single function.
244
- if (isValidBaseType (QTy))
412
+ if (isValidBaseType (QTy, CodeGenOpts ))
245
413
return getBaseTypeInfo (QTy);
246
414
247
415
const Type *Ty = Context.getCanonicalType (QTy).getTypePtr ();
@@ -353,7 +521,7 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
353
521
const CXXRecordDecl *BaseRD = BaseQTy->getAsCXXRecordDecl ();
354
522
if (BaseRD->isEmpty ())
355
523
continue ;
356
- llvm::MDNode *TypeNode = isValidBaseType (BaseQTy)
524
+ llvm::MDNode *TypeNode = isValidBaseType (BaseQTy, CodeGenOpts )
357
525
? getBaseTypeInfo (BaseQTy)
358
526
: getTypeInfo (BaseQTy);
359
527
if (!TypeNode)
@@ -378,8 +546,9 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
378
546
if (Field->isZeroSize (Context) || Field->isUnnamedBitfield ())
379
547
continue ;
380
548
QualType FieldQTy = Field->getType ();
381
- llvm::MDNode *TypeNode = isValidBaseType (FieldQTy) ?
382
- getBaseTypeInfo (FieldQTy) : getTypeInfo (FieldQTy);
549
+ llvm::MDNode *TypeNode = isValidBaseType (FieldQTy, CodeGenOpts)
550
+ ? getBaseTypeInfo (FieldQTy)
551
+ : getTypeInfo (FieldQTy);
383
552
if (!TypeNode)
384
553
return nullptr ;
385
554
@@ -417,7 +586,7 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
417
586
}
418
587
419
588
llvm::MDNode *CodeGenTBAA::getBaseTypeInfo (QualType QTy) {
420
- if (!isValidBaseType (QTy))
589
+ if (!isValidBaseType (QTy, CodeGenOpts ))
421
590
return nullptr ;
422
591
423
592
const Type *Ty = Context.getCanonicalType (QTy).getTypePtr ();
0 commit comments