Skip to content

Commit 61c94b8

Browse files
committed
[TBAA] Emit distinct TBAA tags for pointers with different depths,types.
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)
1 parent baad1b8 commit 61c94b8

File tree

2 files changed

+67
-34
lines changed

2 files changed

+67
-34
lines changed

clang/lib/CodeGen/CodeGenTBAA.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,31 @@ llvm::MDNode *CodeGenTBAA::getTypeInfoHelper(const Type *Ty) {
185185
return getChar();
186186

187187
// Handle pointers and references.
188-
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
189-
// pointers distinct.
190-
if (Ty->isPointerType() || Ty->isReferenceType())
191-
return createScalarTypeNode("any pointer", getChar(), Size);
188+
if (Ty->isPointerType() || Ty->isReferenceType()) {
189+
llvm::MDNode *AnyPtr = createScalarTypeNode("any pointer", getChar(), Size);
190+
// Compute the depth of the pointer and generate a tag of the form "p<depth>
191+
// <base type tag>".
192+
unsigned PtrDepth = 0;
193+
do {
194+
PtrDepth++;
195+
Ty = Ty->getPointeeType().getTypePtr();
196+
} while (Ty->isPointerType() || Ty->isReferenceType());
197+
// TODO: Implement C++'s type "similarity" and consider dis-"similar"
198+
// pointers distinct for non-builtin types.
199+
if (isa<BuiltinType>(Ty)) {
200+
llvm::MDNode *ScalarMD = getTypeInfoHelper(Ty);
201+
StringRef Name =
202+
cast<llvm::MDString>(
203+
ScalarMD->getOperand(CodeGenOpts.NewStructPathTBAA ? 2 : 0))
204+
->getString();
205+
SmallString<256> OutName("p");
206+
OutName += std::to_string(PtrDepth);
207+
OutName += " ";
208+
OutName += Name;
209+
return createScalarTypeNode(OutName, AnyPtr, Size);
210+
}
211+
return AnyPtr;
212+
}
192213

193214
// Accesses to arrays are accesses to objects of their element types.
194215
if (CodeGenOpts.NewStructPathTBAA && Ty->isArrayType())

clang/test/CodeGen/tbaa-pointers.c

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ void p2unsigned(unsigned **ptr) {
44
// CHECK-LABEL: define void @p2unsigned(ptr noundef %ptr)
55
// CHECK-NEXT: entry:
66
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
7-
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0:!.+]]
8-
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
9-
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
7+
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0:!.+]]
8+
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
9+
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0:!.+]]
1010
// CHECK-NEXT: ret void
1111
//
1212
*ptr = 0;
@@ -16,9 +16,9 @@ void p2unsigned_volatile(unsigned *volatile *ptr) {
1616
// CHECK-LABEL: define void @p2unsigned_volatile(ptr noundef %ptr)
1717
// CHECK-NEXT: entry:
1818
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
19-
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
20-
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
21-
// CHECK-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
19+
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
20+
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2INT_0]]
21+
// CHECK-NEXT: store volatile ptr null, ptr [[BASE]], align 8, !tbaa [[P1INT_0]]
2222
// CHECK-NEXT: ret void
2323
//
2424
*ptr = 0;
@@ -28,10 +28,10 @@ void p3int(int ***ptr) {
2828
// CHECK-LABEL: define void @p3int(ptr noundef %ptr)
2929
// CHECK-NEXT: entry:
3030
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
31-
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
32-
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
33-
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
34-
// CHECK-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
31+
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P3INT_0:!.+]]
32+
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P3INT_0]]
33+
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P2INT_0]]
34+
// CHECK-NEXT: store ptr null, ptr [[BASE_1]], align 8, !tbaa [[P1INT_0]]
3535
// CHECK-NEXT: ret void
3636
//
3737
**ptr = 0;
@@ -41,11 +41,11 @@ void p4char(char ****ptr) {
4141
// CHECK-LABEL: define void @p4char(ptr noundef %ptr)
4242
// CHECK-NEXT: entry:
4343
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
44-
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
45-
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
46-
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
47-
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
48-
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
44+
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0:!.+]]
45+
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
46+
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0:!.+]]
47+
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0:!.+]]
48+
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0:!.+]]
4949
// CHECK-NEXT: ret void
5050
//
5151
***ptr = 0;
@@ -55,11 +55,11 @@ void p4char_const1(const char ****ptr) {
5555
// CHECK-LABEL: define void @p4char_const1(ptr noundef %ptr)
5656
// CHECK-NEXT: entry:
5757
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
58-
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
59-
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
60-
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
61-
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
62-
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
58+
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
59+
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
60+
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]]
61+
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]]
62+
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]]
6363
// CHECK-NEXT: ret void
6464
//
6565
***ptr = 0;
@@ -69,11 +69,11 @@ void p4char_const2(const char **const **ptr) {
6969
// CHECK-LABEL: define void @p4char_const2(ptr noundef %ptr)
7070
// CHECK-NEXT: entry:
7171
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
72-
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
73-
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
74-
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[ANY_POINTER_0]]
75-
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[ANY_POINTER_0]]
76-
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[ANY_POINTER_0]]
72+
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
73+
// CHECK-NEXT: [[BASE_0:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P4CHAR_0]]
74+
// CHECK-NEXT: [[BASE_1:%.+]] = load ptr, ptr [[BASE_0]], align 8, !tbaa [[P3CHAR_0]]
75+
// CHECK-NEXT: [[BASE_2:%.+]] = load ptr, ptr [[BASE_1]], align 8, !tbaa [[P2CHAR_0]]
76+
// CHECK-NEXT: store ptr null, ptr [[BASE_2]], align 8, !tbaa [[P1CHAR_0]]
7777
// CHECK-NEXT: ret void
7878
//
7979
***ptr = 0;
@@ -88,16 +88,28 @@ void p2struct(struct S1 **ptr) {
8888
// CHECK-LABEL: define void @p2struct(ptr noundef %ptr)
8989
// CHECK-NEXT: entry:
9090
// CHECK-NEXT: %ptr.addr = alloca ptr, align 8
91-
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
92-
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[ANY_POINTER_0]]
93-
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[ANY_POINTER_0]]
91+
// CHECK-NEXT: store ptr %ptr, ptr %ptr.addr, align 8, !tbaa [[P2S1_0:!.+]]
92+
// CHECK-NEXT: [[BASE:%.+]] = load ptr, ptr %ptr.addr, align 8, !tbaa [[P2S1_0]]
93+
// CHECK-NEXT: store ptr null, ptr [[BASE]], align 8, !tbaa [[P1S1_:!.+]]
9494
// CHECK-NEXT: ret void
9595
//
9696
*ptr = 0;
9797
}
9898

99-
// CHECK: [[ANY_POINTER_0]] = !{[[ANY_POINTER:!.+]], [[ANY_POINTER]], i64 0}
99+
// CHECK: [[P2INT_0]] = !{[[P2INT:!.+]], [[P2INT]], i64 0}
100+
// CHECK: [[P2INT]] = !{!"p2 int", [[ANY_POINTER:!.+]], i64 0}
100101
// CHECK: [[ANY_POINTER]] = !{!"any pointer", [[CHAR:!.+]], i64 0}
101102
// CHECK: [[CHAR]] = !{!"omnipotent char", [[TBAA_ROOT:!.+]], i64 0}
102103
// CHECK: [[TBAA_ROOT]] = !{!"Simple C/C++ TBAA"}
103-
//
104+
// CHECK: [[P1INT_0]] = !{[[P1INT:!.+]], [[P1INT]], i64 0}
105+
// CHECK: [[P1INT]] = !{!"p1 int", [[ANY_POINTER]], i64 0}
106+
// CHECK: [[P3INT_0]] = !{[[P3INT:!.+]], [[P3INT]], i64 0}
107+
// CHECK: [[P3INT]] = !{!"p3 int", [[ANY_POINTER]], i64 0}
108+
// CHECK: [[P4CHAR_0]] = !{[[P4CHAR:!.+]], [[P4CHAR]], i64 0}
109+
// CHECK: [[P4CHAR]] = !{!"p4 omnipotent char", [[ANY_POINTER]], i64 0}
110+
// CHECK: [[P3CHAR_0]] = !{[[P3CHAR:!.+]], [[P3CHAR]], i64 0}
111+
// CHECK: [[P3CHAR]] = !{!"p3 omnipotent char", [[ANY_POINTER]], i64 0}
112+
// CHECK: [[P2CHAR_0]] = !{[[P2CHAR:!.+]], [[P2CHAR]], i64 0}
113+
// CHECK: [[P2CHAR]] = !{!"p2 omnipotent char", [[ANY_POINTER]], i64 0}
114+
// CHECK: [[P1CHAR_0]] = !{[[P1CHAR:!.+]], [[P1CHAR]], i64 0}
115+
// CHECK: [[P1CHAR]] = !{!"p1 omnipotent char", [[ANY_POINTER]], i64 0}

0 commit comments

Comments
 (0)