summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CodeGenTBAA.cpp
diff options
context:
space:
mode:
authorIvan A. Kosarev <ikosarev@accesssoftek.com>2017-11-30 09:26:39 +0000
committerIvan A. Kosarev <ikosarev@accesssoftek.com>2017-11-30 09:26:39 +0000
commitda34247a6aac509f994c57b727a60daf23023e29 (patch)
treee47ab9c5b4b262f3e01482a54331da8cfb4942d2 /clang/lib/CodeGen/CodeGenTBAA.cpp
parent1c14e86a268595ceaa7a28cf8a210931714c1401 (diff)
downloadbcm5719-llvm-da34247a6aac509f994c57b727a60daf23023e29.tar.gz
bcm5719-llvm-da34247a6aac509f994c57b727a60daf23023e29.zip
[CodeGen] Add initial support for union members in TBAA
The basic idea behind this patch is that since in strict aliasing mode all accesses to union members require their outermost enclosing union objects to be specified explicitly, then for a couple given accesses to union members of the form p->a.b.c... q->x.y.z... it is known they can only alias if both p and q point to the same union type and offset ranges of members a.b.c... and x.y.z... overlap. Note that the actual types of the members do not matter. Specifically, in this patch we do the following: * Make unions to be valid TBAA base access types. This enables generation of TBAA type descriptors for unions. * Encode union types as structures with a single member of a special "union member" type. Currently we do not encode information about sizes of types, but conceptually such union members are considered to be of the size of the whole union. * Encode accesses to direct and indirect union members, including member arrays, as accesses to these special members. All accesses to members of a union thus get the same offset, which is the offset of the union they are part of. This means the existing LLVM TBAA machinery is able to handle such accesses with no changes. While this is already an improvement comparing to the current situation, that is, representing all union accesses as may-alias ones, there are further changes planned to complete the support for unions. One of them is storing information about access sizes so we can distinct accesses to non-overlapping union members, including accesses to different elements of member arrays. Another change is encoding type sizes in order to make it possible to compute offsets within constant-indexed array elements. These enhancements will be addressed with separate patches. Differential Revision: https://reviews.llvm.org/D39455 llvm-svn: 319413
Diffstat (limited to 'clang/lib/CodeGen/CodeGenTBAA.cpp')
-rw-r--r--clang/lib/CodeGen/CodeGenTBAA.cpp42
1 files changed, 28 insertions, 14 deletions
diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp
index 2bc4b8a542b..80ad9aecfed 100644
--- a/clang/lib/CodeGen/CodeGenTBAA.cpp
+++ b/clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -74,6 +74,10 @@ llvm::MDNode *CodeGenTBAA::getChar() {
return Char;
}
+llvm::MDNode *CodeGenTBAA::getUnionMemberType(uint64_t Size) {
+ return createScalarTypeNode("union member", getChar(), Size);
+}
+
static bool TypeHasMayAlias(QualType QTy) {
// Tagged types have declarations, and therefore may have attributes.
if (const TagType *TTy = dyn_cast<TagType>(QTy))
@@ -101,9 +105,8 @@ static bool isValidBaseType(QualType QTy) {
return false;
if (RD->hasFlexibleArrayMember())
return false;
- // RD can be struct, union, class, interface or enum.
- // For now, we only handle struct and class.
- if (RD->isStruct() || RD->isClass())
+ // For now, we do not allow interface classes to be base access types.
+ if (RD->isStruct() || RD->isClass() || RD->isUnion())
return true;
}
return false;
@@ -277,18 +280,27 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) {
const RecordDecl *RD = TTy->getDecl()->getDefinition();
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
SmallVector<llvm::MDBuilder::TBAAStructField, 4> Fields;
- for (FieldDecl *Field : RD->fields()) {
- QualType FieldQTy = Field->getType();
- llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
- getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
- if (!TypeNode)
- return BaseTypeMetadataCache[Ty] = nullptr;
-
- uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
- uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
- uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
- Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
+ if (RD->isUnion()) {
+ // Unions are represented as structures with a single member that has a
+ // special type and occupies the whole object.
+ uint64_t Size = Context.getTypeSizeInChars(Ty).getQuantity();
+ llvm::MDNode *TypeNode = getUnionMemberType(Size);
+ Fields.push_back(llvm::MDBuilder::TBAAStructField(/* Offset= */ 0, Size,
TypeNode));
+ } else {
+ for (FieldDecl *Field : RD->fields()) {
+ QualType FieldQTy = Field->getType();
+ llvm::MDNode *TypeNode = isValidBaseType(FieldQTy) ?
+ getBaseTypeInfo(FieldQTy) : getTypeInfo(FieldQTy);
+ if (!TypeNode)
+ return nullptr;
+
+ uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
+ uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
+ uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
+ Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
+ TypeNode));
+ }
}
SmallString<256> OutName;
@@ -333,6 +345,8 @@ llvm::MDNode *CodeGenTBAA::getAccessTagInfo(TBAAAccessInfo Info) {
if (Info.isMayAlias())
Info = TBAAAccessInfo(getChar(), Info.Size);
+ else if (Info.isUnionMember())
+ Info.AccessType = getUnionMemberType(Info.Size);
if (!Info.AccessType)
return nullptr;
OpenPOWER on IntegriCloud