Skip to content

Commit df75183

Browse files
authored
[TBAA] Add verifier for tbaa.struct metadata (#86709)
Adds logic to the IR verifier that checks whether !tbaa.struct nodes are well-formed. That is, it checks that the operands of !tbaa.struct nodes are in groups of three, that each group of three operands consists of two integers and a valid tbaa node, and that the regions described by the offset and size operands are non-overlapping. PR: #86709
1 parent bd9bb31 commit df75183

File tree

9 files changed

+54
-9
lines changed

9 files changed

+54
-9
lines changed

llvm/include/llvm/IR/Verifier.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class TBAAVerifier {
7777
/// Visit an instruction and return true if it is valid, return false if an
7878
/// invalid TBAA is attached.
7979
bool visitTBAAMetadata(Instruction &I, const MDNode *MD);
80+
bool visitTBAAStructMetadata(Instruction &I, const MDNode *MD);
8081
};
8182

8283
/// Check a function for errors, useful for use when debugging a

llvm/lib/IR/Verifier.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5096,6 +5096,9 @@ void Verifier::visitInstruction(Instruction &I) {
50965096
if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa))
50975097
TBAAVerifyHelper.visitTBAAMetadata(I, TBAA);
50985098

5099+
if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa_struct))
5100+
TBAAVerifyHelper.visitTBAAStructMetadata(I, TBAA);
5101+
50995102
if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias))
51005103
visitAliasScopeListMetadata(MD);
51015104
if (MDNode *MD = I.getMetadata(LLVMContext::MD_alias_scope))
@@ -7419,6 +7422,35 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
74197422
return true;
74207423
}
74217424

7425+
bool TBAAVerifier::visitTBAAStructMetadata(Instruction &I, const MDNode *MD) {
7426+
CheckTBAA(MD->getNumOperands() % 3 == 0,
7427+
"tbaa.struct operands must occur in groups of three", &I, MD);
7428+
7429+
// Each group of three operands must consist of two integers and a
7430+
// tbaa node. Moreover, the regions described by the offset and size
7431+
// operands must be non-overlapping.
7432+
std::optional<APInt> NextFree;
7433+
for (unsigned int Idx = 0; Idx < MD->getNumOperands(); Idx += 3) {
7434+
auto *OffsetCI =
7435+
mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(Idx));
7436+
CheckTBAA(OffsetCI, "Offset must be a constant integer", &I, MD);
7437+
7438+
auto *SizeCI =
7439+
mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(Idx + 1));
7440+
CheckTBAA(SizeCI, "Size must be a constant integer", &I, MD);
7441+
7442+
MDNode *TBAA = dyn_cast_or_null<MDNode>(MD->getOperand(Idx + 2));
7443+
CheckTBAA(TBAA, "TBAA tag missing", &I, MD);
7444+
visitTBAAMetadata(I, TBAA);
7445+
7446+
bool NonOverlapping = !NextFree || NextFree->ule(OffsetCI->getValue());
7447+
CheckTBAA(NonOverlapping, "Overlapping tbaa.struct regions", &I, MD);
7448+
7449+
NextFree = OffsetCI->getValue() + SizeCI->getValue();
7450+
}
7451+
return true;
7452+
}
7453+
74227454
char VerifierLegacyPass::ID = 0;
74237455
INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false)
74247456

llvm/test/CodeGen/AArch64/arm64-abi_align.ll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,4 +518,6 @@ attributes #5 = { nobuiltin }
518518
!1 = !{!"omnipotent char", !2}
519519
!2 = !{!"Simple C/C++ TBAA"}
520520
!3 = !{!"short", !1}
521-
!4 = !{i64 0, i64 4, !0, i64 4, i64 2, !3, i64 8, i64 4, !0, i64 12, i64 2, !3, i64 16, i64 4, !0, i64 20, i64 2, !3}
521+
!4 = !{i64 0, i64 4, !5, i64 4, i64 2, !6, i64 8, i64 4, !5, i64 12, i64 2, !6, i64 16, i64 4, !5, i64 20, i64 2, !6}
522+
!5 = !{!0, !0, i64 0}
523+
!6 = !{!3, !3, i64 0}

llvm/test/Transforms/InferAddressSpaces/AMDGPU/mem-intrinsics.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,4 @@ attributes #1 = { argmemonly nounwind }
141141
!5 = distinct !{!5, !"some domain"}
142142
!6 = !{!7}
143143
!7 = distinct !{!7, !5, !"some scope 2"}
144-
!8 = !{i64 0, i64 8, null}
144+
!8 = !{i64 0, i64 8, !0}

llvm/test/Transforms/InstCombine/struct-assign-tbaa.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ entry:
7575
!1 = !{!"omnipotent char", !0}
7676
!2 = !{!5, !5, i64 0}
7777
!3 = !{i64 0, i64 4, !2}
78-
!4 = !{i64 0, i64 8, null}
78+
!4 = !{i64 0, i64 8, !2}
7979
!5 = !{!"float", !0}
8080
!6 = !{i64 0, i64 4, !2, i64 4, i64 4, !2}
8181
!7 = !{i64 0, i64 2, !2, i64 4, i64 6, !2}

llvm/test/Transforms/SROA/tbaa-struct3.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias
539539
!6 = !{!5, !5, i64 0}
540540
!7 = !{i64 0, i64 8, !6, i64 8, i64 4, !1}
541541
!8 = !{i64 0, i64 4, !1, i64 4, i64 8, !6}
542-
!9 = !{i64 0, i64 8, !6, i64 4, i64 8, !1}
542+
!9 = !{i64 0, i64 8, !6, i64 8, i64 8, !1}
543543
!10 = !{i64 0, i64 2, !1, i64 2, i64 2, !1}
544544
!11 = !{i64 0, i64 1, !1, i64 1, i64 3, !1}
545545
!12 = !{i64 0, i64 2, !1, i64 2, i64 6, !1}

llvm/test/Transforms/Scalarizer/basic-inseltpoison.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -836,5 +836,6 @@ define <2 x i32> @f23_crash(<2 x i32> %srcvec, i32 %v1) {
836836
!2 = !{ !"set2", !0 }
837837
!3 = !{ !3, !{!"llvm.loop.parallel_accesses", !13} }
838838
!4 = !{ float 4.0 }
839-
!5 = !{ i64 0, i64 8, null }
839+
!5 = !{ i64 0, i64 8, !6 }
840+
!6 = !{ !1, !1, i64 0 }
840841
!13 = distinct !{}

llvm/test/Transforms/Scalarizer/basic.ll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,5 +870,6 @@ define <2 x float> @f25(<2 x float> %src) {
870870
!2 = !{ !"set2", !0 }
871871
!3 = !{ !3, !{!"llvm.loop.parallel_accesses", !13} }
872872
!4 = !{ float 4.0 }
873-
!5 = !{ i64 0, i64 8, null }
873+
!5 = !{ i64 0, i64 8, !6 }
874+
!6 = !{ !1, !1, i64 0 }
874875
!13 = distinct !{}

llvm/test/Verifier/tbaa-struct.ll

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
1-
; RUN: llvm-as < %s 2>&1
2-
3-
; FIXME: The verifer should reject the invalid !tbaa.struct nodes below.
1+
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
42

53
define void @test_overlapping_regions(ptr %a1) {
4+
; CHECK: Overlapping tbaa.struct regions
5+
; CHECK-NEXT: %ld = load i8, ptr %a1, align 1, !tbaa.struct !0
66
%ld = load i8, ptr %a1, align 1, !tbaa.struct !0
77
ret void
88
}
99

1010
define void @test_size_not_integer(ptr %a1) {
11+
; CHECK: Size must be a constant integer
12+
; CHECK-NEXT: store i8 1, ptr %a1, align 1, !tbaa.struct !5
1113
store i8 1, ptr %a1, align 1, !tbaa.struct !5
1214
ret void
1315
}
1416

1517
define void @test_offset_not_integer(ptr %a1, ptr %a2) {
18+
; CHECK: Offset must be a constant integer
19+
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !6
1620
tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !6
1721
ret void
1822
}
1923

2024
define void @test_tbaa_missing(ptr %a1, ptr %a2) {
25+
; CHECK: TBAA tag missing
26+
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !7
2127
tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 %a1, ptr align 8 %a2, i64 16, i1 false), !tbaa.struct !7
2228
ret void
2329
}
2430

2531
define void @test_tbaa_invalid(ptr %a1) {
32+
; CHECK: Old-style TBAA is no longer allowed, use struct-path TBAA instead
33+
; CHECK-NEXT: store i8 1, ptr %a1, align 1, !tbaa.struct !8
2634
store i8 1, ptr %a1, align 1, !tbaa.struct !8
2735
ret void
2836
}

0 commit comments

Comments
 (0)