strimo378 updated this revision to Diff 525387.
strimo378 added a comment.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

- Updated a test case
- Supporting correct output for -new-struct-path-tbaa
- Added a paragraph to LangRef.rst (see 
https://discourse.llvm.org/t/rfc-clearify-tbaa-struct-requirements-within-language-reference/70835
 )


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D139267/new/

https://reviews.llvm.org/D139267

Files:
  clang/lib/CodeGen/CodeGenTBAA.cpp
  clang/lib/CodeGen/CodeGenTBAA.h
  clang/test/CodeGen/tbaa-struct.cpp
  llvm/docs/LangRef.rst

Index: llvm/docs/LangRef.rst
===================================================================
--- llvm/docs/LangRef.rst
+++ llvm/docs/LangRef.rst
@@ -6406,6 +6406,11 @@
 4 byte gap between the two fields. This gap represents padding which
 does not carry useful data and need not be preserved.
 
+The order of the fields is unspecified. The byte range
+[offset, offset + size) of two fields must not overlap. The size
+of one field might be greater than the size of its TBAA tag (e.g. in
+case of arrays) or might be smaller (e.g. in case of bitfields).
+
 '``noalias``' and '``alias.scope``' Metadata
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
Index: clang/test/CodeGen/tbaa-struct.cpp
===================================================================
--- clang/test/CodeGen/tbaa-struct.cpp
+++ clang/test/CodeGen/tbaa-struct.cpp
@@ -102,6 +102,32 @@
   *a1 = *a2;
 }
 
+struct E {
+  int : 8;
+  int a1 : 8;
+  int : 8;
+  int a2 : 8;
+  
+  int b1 : 9;
+  int : (32-9-9);
+  int b2 : 9;
+
+  int c1 : 15;
+  int c2 : 1;
+  int c3 : 1;
+  int : (32-15-1-1);
+  
+  char dummy[4];
+};
+
+void copy8(E *e1, E *e2) {
+// CHECK-LABEL: _Z5copy8P1ES0_
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 4 dereferenceable(16) %{{.*}}, ptr noundef nonnull align 4 dereferenceable(16) %{{.*}}, i64 16, i1 false)
+// CHECK-OLD-SAME: !tbaa.struct [[TS6:!.*]]
+// CHECK-NEW-SAME: !tbaa [[TAG_E:![0-9]*]]
+  *e1 = *e2;
+}
+
 // CHECK-OLD: [[TS]] = !{i64 0, i64 2, !{{.*}}, i64 4, i64 4, !{{.*}}, i64 8, i64 1, !{{.*}}, i64 12, i64 4, !{{.*}}}
 // CHECK-OLD: [[CHAR:!.*]] = !{!"omnipotent char", !{{.*}}}
 // CHECK-OLD: [[TAG_INT:!.*]] = !{[[INT:!.*]], [[INT]], i64 0}
@@ -113,6 +139,7 @@
 // CHECK-OLD: [[TS3]] = !{i64 0, i64 8, !{{.*}}, i64 0, i64 2, !{{.*}}, i64 4, i64 8, !{{.*}}}
 // CHECK-OLD: [[TS4]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 1, i64 1, [[TAG_CHAR]], i64 2, i64 1, [[TAG_CHAR]]}
 // CHECK-OLD: [[TS5]] = !{i64 0, i64 1, [[TAG_CHAR]], i64 4, i64 1, [[TAG_CHAR]], i64 5, i64 1, [[TAG_CHAR]]}
+// CHECK-OLD: [[TS6]] = !{i64 1, i64 1, [[TAG_INT]], i64 3, i64 1, [[TAG_INT]], i64 4, i64 2, [[TAG_INT]], i64 6, i64 2, [[TAG_INT]], i64 8, i64 2, [[TAG_INT]], i64 10, i64 1, [[TAG_INT]], i64 12, i64 4, [[TAG_CHAR]]}
 
 // CHECK-NEW-DAG: [[TYPE_char:!.*]] = !{{{.*}}, i64 1, !"omnipotent char"}
 // CHECK-NEW-DAG: [[TAG_char]] = !{[[TYPE_char]], [[TYPE_char]], i64 0, i64 0}
@@ -127,3 +154,5 @@
 // CHECK-NEW-DAG: [[TAG_C]] = !{[[TYPE_C]], [[TYPE_C]], i64 0, i64 3}
 // CHECK-NEW-DAG: [[TYPE_D:!.*]] = !{[[TYPE_char]], i64 6, !"_ZTS1D", [[TYPE_char]], i64 0, i64 1, [[TYPE_char]], i64 4, i64 1, [[TYPE_char]], i64 5, i64 1}
 // CHECK-NEW-DAG: [[TAG_D]] = !{[[TYPE_D]], [[TYPE_D]], i64 0, i64 6}
+// CHECK-NEW-DAG: [[TYPE_E:!.*]] = !{[[TYPE_char]], i64 16, !"_ZTS1E", [[TYPE_int]], i64 1, i64 1, [[TYPE_int]], i64 3, i64 1, [[TYPE_int]], i64 4, i64 2, [[TYPE_int]], i64 6, i64 2, [[TYPE_int]], i64 8, i64 2, [[TYPE_int]], i64 9, i64 1, [[TYPE_int]], i64 10, i64 1, [[TYPE_char]], i64 12, i64 4}
+// CHECK-NEW-DAG: [[TAG_E]] = !{[[TYPE_E]], [[TYPE_E]], i64 0, i64 16}
Index: clang/lib/CodeGen/CodeGenTBAA.h
===================================================================
--- clang/lib/CodeGen/CodeGenTBAA.h
+++ clang/lib/CodeGen/CodeGenTBAA.h
@@ -146,6 +146,12 @@
   /// considered to be equivalent to it.
   llvm::MDNode *getChar();
 
+  /// AddCollectedField - Add one collected field to Fields vector
+  void
+  AddCollectedField(SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &Fields,
+                    uint64_t Offset, uint64_t Size, QualType QTy, bool MayAlias,
+                    bool FuseOverlapping);
+
   /// CollectFields - Collect information about the fields of a type for
   /// !tbaa.struct metadata formation. Return false for an unsupported type.
   bool CollectFields(uint64_t BaseOffset,
Index: clang/lib/CodeGen/CodeGenTBAA.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenTBAA.cpp
+++ clang/lib/CodeGen/CodeGenTBAA.cpp
@@ -272,13 +272,44 @@
                         Size);
 }
 
+void CodeGenTBAA::AddCollectedField(
+    SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &Fields, uint64_t Offset,
+    uint64_t Size, QualType QTy, bool MayAlias, bool FuseOverlapping) {
+
+  // Fuse fields that overlap in their byte position (e.g. caused by bitfields)
+  if (FuseOverlapping && !Fields.empty() && Fields.back().Offset <= Offset &&
+      Offset < Fields.back().Offset + Fields.back().Size) {
+    Fields.back().Size = (Offset + Size) - Fields.back().Offset;
+    return;
+  }
+
+  llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy);
+  llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
+  Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
+}
+
+// Calculate the number of bytes a bitfield affects.
+// E.g. a 6-bit field starting a bit 0 affects 1 byte,
+// a 6-bit field starting at bit 4 affects 2 bytes.
+static uint64_t getBitFieldByteSize(ASTContext &Context,
+                                    uint64_t FieldBitOffset,
+                                    const FieldDecl *Field) {
+  assert(Field->isBitField());
+
+  uint64_t LastBitOffset =
+      FieldBitOffset + Field->getBitWidthValue(Context) - 1;
+  uint64_t LastByteOffset = LastBitOffset / Context.getCharWidth();
+  uint64_t FirstByteOffset = FieldBitOffset / Context.getCharWidth();
+  return LastByteOffset - FirstByteOffset + 1;
+}
+
 bool
 CodeGenTBAA::CollectFields(uint64_t BaseOffset,
                            QualType QTy,
                            SmallVectorImpl<llvm::MDBuilder::TBAAStructField> &
                              Fields,
                            bool MayAlias) {
-  /* Things not handled yet include: C++ base classes, bitfields, */
+  /* Things not handled yet include: C++ base classes */
 
   if (const RecordType *TTy = QTy->getAs<RecordType>()) {
     const RecordDecl *RD = TTy->getDecl()->getDefinition();
@@ -300,19 +331,23 @@
       uint64_t Offset = BaseOffset +
                         Layout.getFieldOffset(idx) / Context.getCharWidth();
       QualType FieldQTy = i->getType();
-      if (!CollectFields(Offset, FieldQTy, Fields,
-                         MayAlias || TypeHasMayAlias(FieldQTy)))
-        return false;
+      bool FieldMayAlias = MayAlias || TypeHasMayAlias(FieldQTy);
+      if ((*i)->isBitField()) {
+        uint64_t Size =
+            getBitFieldByteSize(Context, Layout.getFieldOffset(idx), *i);
+
+        AddCollectedField(Fields, Offset, Size, FieldQTy, FieldMayAlias, true);
+      } else {
+        if (!CollectFields(Offset, FieldQTy, Fields, FieldMayAlias))
+          return false;
+      }
     }
     return true;
   }
 
   /* Otherwise, treat whatever it is as a field. */
-  uint64_t Offset = BaseOffset;
   uint64_t Size = Context.getTypeSizeInChars(QTy).getQuantity();
-  llvm::MDNode *TBAAType = MayAlias ? getChar() : getTypeInfo(QTy);
-  llvm::MDNode *TBAATag = getAccessTagInfo(TBAAAccessInfo(TBAAType, Size));
-  Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size, TBAATag));
+  AddCollectedField(Fields, BaseOffset, Size, QTy, MayAlias, false);
   return true;
 }
 
@@ -382,7 +417,10 @@
 
       uint64_t BitOffset = Layout.getFieldOffset(Field->getFieldIndex());
       uint64_t Offset = Context.toCharUnitsFromBits(BitOffset).getQuantity();
-      uint64_t Size = Context.getTypeSizeInChars(FieldQTy).getQuantity();
+      uint64_t Size = Field->isBitField()
+                          ? getBitFieldByteSize(Context, BitOffset, Field)
+                          : Context.getTypeSizeInChars(FieldQTy).getQuantity();
+
       Fields.push_back(llvm::MDBuilder::TBAAStructField(Offset, Size,
                                                         TypeNode));
     }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to