xref: /aosp_15_r20/external/clang/lib/CodeGen/CodeGenTBAA.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- CodeGenTypes.cpp - TBAA information for LLVM CodeGen -------------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This is the code that manages TBAA information and defines the TBAA policy
11*67e74705SXin Li // for the optimizer to use. Relevant standards text includes:
12*67e74705SXin Li //
13*67e74705SXin Li //   C99 6.5p7
14*67e74705SXin Li //   C++ [basic.lval] (p10 in n3126, p15 in some earlier versions)
15*67e74705SXin Li //
16*67e74705SXin Li //===----------------------------------------------------------------------===//
17*67e74705SXin Li 
18*67e74705SXin Li #include "CodeGenTBAA.h"
19*67e74705SXin Li #include "clang/AST/ASTContext.h"
20*67e74705SXin Li #include "clang/AST/Attr.h"
21*67e74705SXin Li #include "clang/AST/Mangle.h"
22*67e74705SXin Li #include "clang/AST/RecordLayout.h"
23*67e74705SXin Li #include "clang/Frontend/CodeGenOptions.h"
24*67e74705SXin Li #include "llvm/ADT/SmallSet.h"
25*67e74705SXin Li #include "llvm/IR/Constants.h"
26*67e74705SXin Li #include "llvm/IR/LLVMContext.h"
27*67e74705SXin Li #include "llvm/IR/Metadata.h"
28*67e74705SXin Li #include "llvm/IR/Type.h"
29*67e74705SXin Li using namespace clang;
30*67e74705SXin Li using namespace CodeGen;
31*67e74705SXin Li 
CodeGenTBAA(ASTContext & Ctx,llvm::LLVMContext & VMContext,const CodeGenOptions & CGO,const LangOptions & Features,MangleContext & MContext)32*67e74705SXin Li CodeGenTBAA::CodeGenTBAA(ASTContext &Ctx, llvm::LLVMContext& VMContext,
33*67e74705SXin Li                          const CodeGenOptions &CGO,
34*67e74705SXin Li                          const LangOptions &Features, MangleContext &MContext)
35*67e74705SXin Li   : Context(Ctx), CodeGenOpts(CGO), Features(Features), MContext(MContext),
36*67e74705SXin Li     MDHelper(VMContext), Root(nullptr), Char(nullptr) {
37*67e74705SXin Li }
38*67e74705SXin Li 
~CodeGenTBAA()39*67e74705SXin Li CodeGenTBAA::~CodeGenTBAA() {
40*67e74705SXin Li }
41*67e74705SXin Li 
getRoot()42*67e74705SXin Li llvm::MDNode *CodeGenTBAA::getRoot() {
43*67e74705SXin Li   // Define the root of the tree. This identifies the tree, so that
44*67e74705SXin Li   // if our LLVM IR is linked with LLVM IR from a different front-end
45*67e74705SXin Li   // (or a different version of this front-end), their TBAA trees will
46*67e74705SXin Li   // remain distinct, and the optimizer will treat them conservatively.
47*67e74705SXin Li   if (!Root) {
48*67e74705SXin Li     if (Features.CPlusPlus)
49*67e74705SXin Li       Root = MDHelper.createTBAARoot("Simple C++ TBAA");
50*67e74705SXin Li     else
51*67e74705SXin Li       Root = MDHelper.createTBAARoot("Simple C/C++ TBAA");
52*67e74705SXin Li   }
53*67e74705SXin Li 
54*67e74705SXin Li   return Root;
55*67e74705SXin Li }
56*67e74705SXin Li 
57*67e74705SXin Li // For both scalar TBAA and struct-path aware TBAA, the scalar type has the
58*67e74705SXin Li // same format: name, parent node, and offset.
createTBAAScalarType(StringRef Name,llvm::MDNode * Parent)59*67e74705SXin Li llvm::MDNode *CodeGenTBAA::createTBAAScalarType(StringRef Name,
60*67e74705SXin Li                                                 llvm::MDNode *Parent) {
61*67e74705SXin Li   return MDHelper.createTBAAScalarTypeNode(Name, Parent);
62*67e74705SXin Li }
63*67e74705SXin Li 
getChar()64*67e74705SXin Li llvm::MDNode *CodeGenTBAA::getChar() {
65*67e74705SXin Li   // Define the root of the tree for user-accessible memory. C and C++
66*67e74705SXin Li   // give special powers to char and certain similar types. However,
67*67e74705SXin Li   // these special powers only cover user-accessible memory, and doesn't
68*67e74705SXin Li   // include things like vtables.
69*67e74705SXin Li   if (!Char)
70*67e74705SXin Li     Char = createTBAAScalarType("omnipotent char", getRoot());
71*67e74705SXin Li 
72*67e74705SXin Li   return Char;
73*67e74705SXin Li }
74*67e74705SXin Li 
TypeHasMayAlias(QualType QTy)75*67e74705SXin Li static bool TypeHasMayAlias(QualType QTy) {
76*67e74705SXin Li   // Tagged types have declarations, and therefore may have attributes.
77*67e74705SXin Li   if (const TagType *TTy = dyn_cast<TagType>(QTy))
78*67e74705SXin Li     return TTy->getDecl()->hasAttr<MayAliasAttr>();
79*67e74705SXin Li 
80*67e74705SXin Li   // Typedef types have declarations, and therefore may have attributes.
81*67e74705SXin Li   if (const TypedefType *TTy = dyn_cast<TypedefType>(QTy)) {
82*67e74705SXin Li     if (TTy->getDecl()->hasAttr<MayAliasAttr>())
83*67e74705SXin Li       return true;
84*67e74705SXin Li     // Also, their underlying types may have relevant attributes.
85*67e74705SXin Li     return TypeHasMayAlias(TTy->desugar());
86*67e74705SXin Li   }
87*67e74705SXin Li 
88*67e74705SXin Li   return false;
89*67e74705SXin Li }
90*67e74705SXin Li 
91*67e74705SXin Li llvm::MDNode *
getTBAAInfo(QualType QTy)92*67e74705SXin Li CodeGenTBAA::getTBAAInfo(QualType QTy) {
93*67e74705SXin Li   // At -O0 or relaxed aliasing, TBAA is not emitted for regular types.
94*67e74705SXin Li   if (CodeGenOpts.OptimizationLevel == 0 || CodeGenOpts.RelaxedAliasing)
95*67e74705SXin Li     return nullptr;
96*67e74705SXin Li 
97*67e74705SXin Li   // If the type has the may_alias attribute (even on a typedef), it is
98*67e74705SXin Li   // effectively in the general char alias class.
99*67e74705SXin Li   if (TypeHasMayAlias(QTy))
100*67e74705SXin Li     return getChar();
101*67e74705SXin Li 
102*67e74705SXin Li   const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
103*67e74705SXin Li 
104*67e74705SXin Li   if (llvm::MDNode *N = MetadataCache[Ty])
105*67e74705SXin Li     return N;
106*67e74705SXin Li 
107*67e74705SXin Li   // Handle builtin types.
108*67e74705SXin Li   if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) {
109*67e74705SXin Li     switch (BTy->getKind()) {
110*67e74705SXin Li     // Character types are special and can alias anything.
111*67e74705SXin Li     // In C++, this technically only includes "char" and "unsigned char",
112*67e74705SXin Li     // and not "signed char". In C, it includes all three. For now,
113*67e74705SXin Li     // the risk of exploiting this detail in C++ seems likely to outweigh
114*67e74705SXin Li     // the benefit.
115*67e74705SXin Li     case BuiltinType::Char_U:
116*67e74705SXin Li     case BuiltinType::Char_S:
117*67e74705SXin Li     case BuiltinType::UChar:
118*67e74705SXin Li     case BuiltinType::SChar:
119*67e74705SXin Li       return getChar();
120*67e74705SXin Li 
121*67e74705SXin Li     // Unsigned types can alias their corresponding signed types.
122*67e74705SXin Li     case BuiltinType::UShort:
123*67e74705SXin Li       return getTBAAInfo(Context.ShortTy);
124*67e74705SXin Li     case BuiltinType::UInt:
125*67e74705SXin Li       return getTBAAInfo(Context.IntTy);
126*67e74705SXin Li     case BuiltinType::ULong:
127*67e74705SXin Li       return getTBAAInfo(Context.LongTy);
128*67e74705SXin Li     case BuiltinType::ULongLong:
129*67e74705SXin Li       return getTBAAInfo(Context.LongLongTy);
130*67e74705SXin Li     case BuiltinType::UInt128:
131*67e74705SXin Li       return getTBAAInfo(Context.Int128Ty);
132*67e74705SXin Li 
133*67e74705SXin Li     // Treat all other builtin types as distinct types. This includes
134*67e74705SXin Li     // treating wchar_t, char16_t, and char32_t as distinct from their
135*67e74705SXin Li     // "underlying types".
136*67e74705SXin Li     default:
137*67e74705SXin Li       return MetadataCache[Ty] =
138*67e74705SXin Li         createTBAAScalarType(BTy->getName(Features), getChar());
139*67e74705SXin Li     }
140*67e74705SXin Li   }
141*67e74705SXin Li 
142*67e74705SXin Li   // Handle pointers.
143*67e74705SXin Li   // TODO: Implement C++'s type "similarity" and consider dis-"similar"
144*67e74705SXin Li   // pointers distinct.
145*67e74705SXin Li   if (Ty->isPointerType())
146*67e74705SXin Li     return MetadataCache[Ty] = createTBAAScalarType("any pointer",
147*67e74705SXin Li                                                     getChar());
148*67e74705SXin Li 
149*67e74705SXin Li   // Enum types are distinct types. In C++ they have "underlying types",
150*67e74705SXin Li   // however they aren't related for TBAA.
151*67e74705SXin Li   if (const EnumType *ETy = dyn_cast<EnumType>(Ty)) {
152*67e74705SXin Li     // In C++ mode, types have linkage, so we can rely on the ODR and
153*67e74705SXin Li     // on their mangled names, if they're external.
154*67e74705SXin Li     // TODO: Is there a way to get a program-wide unique name for a
155*67e74705SXin Li     // decl with local linkage or no linkage?
156*67e74705SXin Li     if (!Features.CPlusPlus || !ETy->getDecl()->isExternallyVisible())
157*67e74705SXin Li       return MetadataCache[Ty] = getChar();
158*67e74705SXin Li 
159*67e74705SXin Li     SmallString<256> OutName;
160*67e74705SXin Li     llvm::raw_svector_ostream Out(OutName);
161*67e74705SXin Li     MContext.mangleTypeName(QualType(ETy, 0), Out);
162*67e74705SXin Li     return MetadataCache[Ty] = createTBAAScalarType(OutName, getChar());
163*67e74705SXin Li   }
164*67e74705SXin Li 
165*67e74705SXin Li   // For now, handle any other kind of type conservatively.
166*67e74705SXin Li   return MetadataCache[Ty] = getChar();
167*67e74705SXin Li }
168*67e74705SXin Li 
getTBAAInfoForVTablePtr()169*67e74705SXin Li llvm::MDNode *CodeGenTBAA::getTBAAInfoForVTablePtr() {
170*67e74705SXin Li   return createTBAAScalarType("vtable pointer", getRoot());
171*67e74705SXin Li }
172*67e74705SXin Li 
173*67e74705SXin Li bool
CollectFields(uint64_t BaseOffset,QualType QTy,SmallVectorImpl<llvm::MDBuilder::TBAAStructField> & Fields,bool MayAlias)174*67e74705SXin Li CodeGenTBAA::CollectFields(uint64_t BaseOffset,
175*67e74705SXin Li                            QualType QTy,
176*67e74705SXin Li                            SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &
177*67e74705SXin Li                              Fields,
178*67e74705SXin Li                            bool MayAlias) {
179*67e74705SXin Li   /* Things not handled yet include: C++ base classes, bitfields, */
180*67e74705SXin Li 
181*67e74705SXin Li   if (const RecordType *TTy = QTy->getAs<RecordType>()) {
182*67e74705SXin Li     const RecordDecl *RD = TTy->getDecl()->getDefinition();
183*67e74705SXin Li     if (RD->hasFlexibleArrayMember())
184*67e74705SXin Li       return false;
185*67e74705SXin Li 
186*67e74705SXin Li     // TODO: Handle C++ base classes.
187*67e74705SXin Li     if (const CXXRecordDecl *Decl = dyn_cast<CXXRecordDecl>(RD))
188*67e74705SXin Li       if (Decl->bases_begin() != Decl->bases_end())
189*67e74705SXin Li         return false;
190*67e74705SXin Li 
191*67e74705SXin Li     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
192*67e74705SXin Li 
193*67e74705SXin Li     unsigned idx = 0;
194*67e74705SXin Li     for (RecordDecl::field_iterator i = RD->field_begin(),
195*67e74705SXin Li          e = RD->field_end(); i != e; ++i, ++idx) {
196*67e74705SXin Li       uint64_t Offset = BaseOffset +
197*67e74705SXin Li                         Layout.getFieldOffset(idx) / Context.getCharWidth();
198*67e74705SXin Li       QualType FieldQTy = i->getType();
199*67e74705SXin Li       if (!CollectFields(Offset, FieldQTy, Fields,
200*67e74705SXin Li                          MayAlias || TypeHasMayAlias(FieldQTy)))
201*67e74705SXin Li         return false;
202*67e74705SXin Li     }
203*67e74705SXin Li     return true;
204*67e74705SXin Li   }
205*67e74705SXin Li 
206*67e74705SXin Li   /* Otherwise, treat whatever it is as a field. */
207*67e74705SXin Li   uint64_t Offset = BaseOffset;
208*67e74705SXin Li   uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
209*67e74705SXin Li   llvm::MDNode *TBAAInfo = MayAlias ? getChar() : getTBAAInfo(QTy);
210*67e74705SXin Li   llvm::MDNode *TBAATag = getTBAAScalarTagInfo(TBAAInfo);
211*67e74705SXin Li   Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
212*67e74705SXin Li   return true;
213*67e74705SXin Li }
214*67e74705SXin Li 
215*67e74705SXin Li llvm::MDNode *
getTBAAStructInfo(QualType QTy)216*67e74705SXin Li CodeGenTBAA::getTBAAStructInfo(QualType QTy) {
217*67e74705SXin Li   const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
218*67e74705SXin Li 
219*67e74705SXin Li   if (llvm::MDNode *N = StructMetadataCache[Ty])
220*67e74705SXin Li     return N;
221*67e74705SXin Li 
222*67e74705SXin Li   SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
223*67e74705SXin Li   if (CollectFields(0, QTy, Fields, TypeHasMayAlias(QTy)))
224*67e74705SXin Li     return MDHelper.createTBAAStructNode(Fields);
225*67e74705SXin Li 
226*67e74705SXin Li   // For now, handle any other kind of type conservatively.
227*67e74705SXin Li   return StructMetadataCache[Ty] = nullptr;
228*67e74705SXin Li }
229*67e74705SXin Li 
230*67e74705SXin Li /// Check if the given type can be handled by path-aware TBAA.
isTBAAPathStruct(QualType QTy)231*67e74705SXin Li static bool isTBAAPathStruct(QualType QTy) {
232*67e74705SXin Li   if (const RecordType *TTy = QTy->getAs<RecordType>()) {
233*67e74705SXin Li     const RecordDecl *RD = TTy->getDecl()->getDefinition();
234*67e74705SXin Li     if (RD->hasFlexibleArrayMember())
235*67e74705SXin Li       return false;
236*67e74705SXin Li     // RD can be struct, union, class, interface or enum.
237*67e74705SXin Li     // For now, we only handle struct and class.
238*67e74705SXin Li     if (RD->isStruct() || RD->isClass())
239*67e74705SXin Li       return true;
240*67e74705SXin Li   }
241*67e74705SXin Li   return false;
242*67e74705SXin Li }
243*67e74705SXin Li 
244*67e74705SXin Li llvm::MDNode *
getTBAAStructTypeInfo(QualType QTy)245*67e74705SXin Li CodeGenTBAA::getTBAAStructTypeInfo(QualType QTy) {
246*67e74705SXin Li   const Type *Ty = Context.getCanonicalType(QTy).getTypePtr();
247*67e74705SXin Li   assert(isTBAAPathStruct(QTy));
248*67e74705SXin Li 
249*67e74705SXin Li   if (llvm::MDNode *N = StructTypeMetadataCache[Ty])
250*67e74705SXin Li     return N;
251*67e74705SXin Li 
252*67e74705SXin Li   if (const RecordType *TTy = QTy->getAs<RecordType>()) {
253*67e74705SXin Li     const RecordDecl *RD = TTy->getDecl()->getDefinition();
254*67e74705SXin Li 
255*67e74705SXin Li     const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
256*67e74705SXin Li     SmallVector <std::pair<llvm::MDNode*, uint64_t>, 4> Fields;
257*67e74705SXin Li     unsigned idx = 0;
258*67e74705SXin Li     for (RecordDecl::field_iterator i = RD->field_begin(),
259*67e74705SXin Li          e = RD->field_end(); i != e; ++i, ++idx) {
260*67e74705SXin Li       QualType FieldQTy = i->getType();
261*67e74705SXin Li       llvm::MDNode *FieldNode;
262*67e74705SXin Li       if (isTBAAPathStruct(FieldQTy))
263*67e74705SXin Li         FieldNode = getTBAAStructTypeInfo(FieldQTy);
264*67e74705SXin Li       else
265*67e74705SXin Li         FieldNode = getTBAAInfo(FieldQTy);
266*67e74705SXin Li       if (!FieldNode)
267*67e74705SXin Li         return StructTypeMetadataCache[Ty] = nullptr;
268*67e74705SXin Li       Fields.push_back(std::make_pair(
269*67e74705SXin Li           FieldNode, Layout.getFieldOffset(idx) / Context.getCharWidth()));
270*67e74705SXin Li     }
271*67e74705SXin Li 
272*67e74705SXin Li     SmallString<256> OutName;
273*67e74705SXin Li     if (Features.CPlusPlus) {
274*67e74705SXin Li       // Don't use the mangler for C code.
275*67e74705SXin Li       llvm::raw_svector_ostream Out(OutName);
276*67e74705SXin Li       MContext.mangleTypeName(QualType(Ty, 0), Out);
277*67e74705SXin Li     } else {
278*67e74705SXin Li       OutName = RD->getName();
279*67e74705SXin Li     }
280*67e74705SXin Li     // Create the struct type node with a vector of pairs (offset, type).
281*67e74705SXin Li     return StructTypeMetadataCache[Ty] =
282*67e74705SXin Li       MDHelper.createTBAAStructTypeNode(OutName, Fields);
283*67e74705SXin Li   }
284*67e74705SXin Li 
285*67e74705SXin Li   return StructMetadataCache[Ty] = nullptr;
286*67e74705SXin Li }
287*67e74705SXin Li 
288*67e74705SXin Li /// Return a TBAA tag node for both scalar TBAA and struct-path aware TBAA.
289*67e74705SXin Li llvm::MDNode *
getTBAAStructTagInfo(QualType BaseQTy,llvm::MDNode * AccessNode,uint64_t Offset)290*67e74705SXin Li CodeGenTBAA::getTBAAStructTagInfo(QualType BaseQTy, llvm::MDNode *AccessNode,
291*67e74705SXin Li                                   uint64_t Offset) {
292*67e74705SXin Li   if (!AccessNode)
293*67e74705SXin Li     return nullptr;
294*67e74705SXin Li 
295*67e74705SXin Li   if (!CodeGenOpts.StructPathTBAA)
296*67e74705SXin Li     return getTBAAScalarTagInfo(AccessNode);
297*67e74705SXin Li 
298*67e74705SXin Li   const Type *BTy = Context.getCanonicalType(BaseQTy).getTypePtr();
299*67e74705SXin Li   TBAAPathTag PathTag = TBAAPathTag(BTy, AccessNode, Offset);
300*67e74705SXin Li   if (llvm::MDNode *N = StructTagMetadataCache[PathTag])
301*67e74705SXin Li     return N;
302*67e74705SXin Li 
303*67e74705SXin Li   llvm::MDNode *BNode = nullptr;
304*67e74705SXin Li   if (isTBAAPathStruct(BaseQTy))
305*67e74705SXin Li     BNode  = getTBAAStructTypeInfo(BaseQTy);
306*67e74705SXin Li   if (!BNode)
307*67e74705SXin Li     return StructTagMetadataCache[PathTag] =
308*67e74705SXin Li        MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0);
309*67e74705SXin Li 
310*67e74705SXin Li   return StructTagMetadataCache[PathTag] =
311*67e74705SXin Li     MDHelper.createTBAAStructTagNode(BNode, AccessNode, Offset);
312*67e74705SXin Li }
313*67e74705SXin Li 
314*67e74705SXin Li llvm::MDNode *
getTBAAScalarTagInfo(llvm::MDNode * AccessNode)315*67e74705SXin Li CodeGenTBAA::getTBAAScalarTagInfo(llvm::MDNode *AccessNode) {
316*67e74705SXin Li   if (!AccessNode)
317*67e74705SXin Li     return nullptr;
318*67e74705SXin Li   if (llvm::MDNode *N = ScalarTagMetadataCache[AccessNode])
319*67e74705SXin Li     return N;
320*67e74705SXin Li 
321*67e74705SXin Li   return ScalarTagMetadataCache[AccessNode] =
322*67e74705SXin Li     MDHelper.createTBAAStructTagNode(AccessNode, AccessNode, 0);
323*67e74705SXin Li }
324