Skip to content

Commit

Permalink
[TBAA] Emit distinct TBAA tags for pointers with different depths,types.
Browse files Browse the repository at this point in the history
This patch extends Clang's TBAA generation code to emit distinct tags
for incompatible pointer types.

Pointers with different element types are incompatible if the pointee
types are also incompatible (modulo sugar/modifiers).

Express this in TBAA by generating different tags for pointers based
on the pointer depth and pointee type. To get the TBAA tag for the
pointee type it uses getTypeInfoHelper on the pointee type.

(Moved from https://reviews.llvm.org/D122573)
  • Loading branch information
fhahn committed Jun 11, 2024
1 parent baad1b8 commit 61c94b8
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 34 deletions.
29 changes: 25 additions & 4 deletions clang/lib/CodeGen/CodeGenTBAA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,31 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
return getChar();

// Handle pointers and references.
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
// pointers distinct.
if (Ty->isPointerType() || Ty->isReferenceType())
return createScalarTypeNode("any pointer", getChar(), Size);
if (Ty->isPointerType() || Ty->isReferenceType()) {
llvm::MDNode *AnyPtr = createScalarTypeNode("any pointer", getChar(), Size);
// Compute the depth of the pointer and generate a tag of the form "p<depth>
// <base type tag>".
unsigned PtrDepth = 0;
do {
PtrDepth++;
Ty = Ty->getPointeeType().getTypePtr();
} while (Ty->isPointerType() || Ty->isReferenceType());
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
// pointers distinct for non-builtin types.
if (isa<BuiltinType>(Ty)) {
llvm::MDNode *ScalarMD = getTypeInfoHelper(Ty);
StringRef Name =
cast<llvm::MDString>(
ScalarMD->getOperand(CodeGenOpts.NewStructPathTBAA ? 2 : 0))
->getString();
SmallString<256> OutName("p");
OutName += std::to_string(PtrDepth);
OutName += " ";
OutName += Name;
return createScalarTypeNode(OutName, AnyPtr, Size);
}
return AnyPtr;
}

// Accesses to arrays are accesses to objects of their element types.
if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType())
Expand Down
72 changes: 42 additions & 30 deletions clang/test/CodeGen/tbaa-pointers.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ void p2unsigned(unsigned **ptr) {
// CHECK-LABEL: define void @p2unsigned(ptr noundef %ptr)
// CHECK-NEXT: entry:
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0:!.+]]
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0:!.+]]
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0:!.+]]
// CHECK-NEXT: ret void
//
*ptr = 0;
Expand All @@ -16,9 +16,9 @@ void p2unsigned_volatile(unsigned *volatile *ptr) {
// CHECK-LABEL: define void @p2unsigned_volatile(ptr noundef %ptr)
// CHECK-NEXT: entry:
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
// CHECK-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0]]
// CHECK-NEXT: ret void
//
*ptr = 0;
Expand All @@ -28,10 +28,10 @@ void p3int(int ***ptr) {
// CHECK-LABEL: define void @p3int(ptr noundef %ptr)
// CHECK-NEXT: entry:
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P3INT_0:!.+]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P3INT_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P2INT_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[P1INT_0]]
// CHECK-NEXT: ret void
//
**ptr = 0;
Expand All @@ -41,11 +41,11 @@ void p4char(char ****ptr) {
// CHECK-LABEL: define void @p4char(ptr noundef %ptr)
// CHECK-NEXT: entry:
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0:!.+]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0:!.+]]
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0:!.+]]
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0:!.+]]
// CHECK-NEXT: ret void
//
***ptr = 0;
Expand All @@ -55,11 +55,11 @@ void p4char_const1(const char ****ptr) {
// CHECK-LABEL: define void @p4char_const1(ptr noundef %ptr)
// CHECK-NEXT: entry:
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]]
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]]
// CHECK-NEXT: ret void
//
***ptr = 0;
Expand All @@ -69,11 +69,11 @@ void p4char_const2(const char **const **ptr) {
// CHECK-LABEL: define void @p4char_const2(ptr noundef %ptr)
// CHECK-NEXT: entry:
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]]
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]]
// CHECK-NEXT: ret void
//
***ptr = 0;
Expand All @@ -88,16 +88,28 @@ void p2struct(struct S1 **ptr) {
// CHECK-LABEL: define void @p2struct(ptr noundef %ptr)
// CHECK-NEXT: entry:
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2S1_0:!.+]]
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2S1_0]]
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_:!.+]]
// CHECK-NEXT: ret void
//
*ptr = 0;
}

// CHECK: [[ANY_POINTER_0]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0}
// CHECK: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0}
// CHECK: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0}
// CHECK: [[ANY_POINTER]] = !{!"any pointer", [[CHAR:!.+]], i64 0}
// CHECK: [[CHAR]] = !{!"omnipotent char", [[TBAA_ROOT:!.+]], i64 0}
// CHECK: [[TBAA_ROOT]] = !{!"Simple C/C++ TBAA"}
//
// CHECK: [[P1INT_0]] = !{[[P1INT:!.+]], [[P1INT]], i64 0}
// CHECK: [[P1INT]] = !{!"p1 int", [[ANY_POINTER]], i64 0}
// CHECK: [[P3INT_0]] = !{[[P3INT:!.+]], [[P3INT]], i64 0}
// CHECK: [[P3INT]] = !{!"p3 int", [[ANY_POINTER]], i64 0}
// CHECK: [[P4CHAR_0]] = !{[[P4CHAR:!.+]], [[P4CHAR]], i64 0}
// CHECK: [[P4CHAR]] = !{!"p4 omnipotent char", [[ANY_POINTER]], i64 0}
// CHECK: [[P3CHAR_0]] = !{[[P3CHAR:!.+]], [[P3CHAR]], i64 0}
// CHECK: [[P3CHAR]] = !{!"p3 omnipotent char", [[ANY_POINTER]], i64 0}
// CHECK: [[P2CHAR_0]] = !{[[P2CHAR:!.+]], [[P2CHAR]], i64 0}
// CHECK: [[P2CHAR]] = !{!"p2 omnipotent char", [[ANY_POINTER]], i64 0}
// CHECK: [[P1CHAR_0]] = !{[[P1CHAR:!.+]], [[P1CHAR]], i64 0}
// CHECK: [[P1CHAR]] = !{!"p1 omnipotent char", [[ANY_POINTER]], i64 0}

0 comments on commit 61c94b8

Please sign in to comment.