Skip to content

Commit 5be3d8b

Browse files
committed
wip
1 parent a61ca99 commit 5be3d8b

25 files changed

+328
-219
lines changed

clang/test/CodeGen/allow-ubsan-check.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ int div(int x, int y) {
8686
}
8787

8888
// CHECK-LABEL: define dso_local i32 @null(
89-
// CHECK-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
89+
// CHECK-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
9090
// CHECK-NEXT: [[ENTRY:.*:]]
9191
// CHECK-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
9292
//
@@ -102,7 +102,7 @@ int div(int x, int y) {
102102
// CHECK-NEXT: ret i32 [[TMP2]]
103103
//
104104
// TR-LABEL: define dso_local i32 @null(
105-
// TR-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
105+
// TR-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
106106
// TR-NEXT: [[ENTRY:.*:]]
107107
// TR-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
108108
// TR-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 29), !nosanitize [[META2]]
@@ -116,7 +116,7 @@ int div(int x, int y) {
116116
// TR-NEXT: ret i32 [[TMP2]]
117117
//
118118
// REC-LABEL: define dso_local i32 @null(
119-
// REC-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
119+
// REC-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] {
120120
// REC-NEXT: [[ENTRY:.*:]]
121121
// REC-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]]
122122
// REC-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 29), !nosanitize [[META2]]

clang/test/CodeGenCXX/RelativeVTablesABI/dynamic-cast.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O3 -o - -emit-llvm | FileCheck %s
55

6-
// CHECK: define{{.*}} ptr @_Z6upcastP1B(ptr noundef readnone returned %b) local_unnamed_addr
6+
// CHECK: define{{.*}} ptr @_Z6upcastP1B(ptr noundef readnone returned captures(ret: address, provenance) %b) local_unnamed_addr
77
// CHECK-NEXT: entry:
88
// CHECK-NEXT: ret ptr %b
99
// CHECK-NEXT: }
@@ -22,12 +22,12 @@
2222

2323
// CHECK: declare ptr @__dynamic_cast(ptr, ptr, ptr, i64) local_unnamed_addr
2424

25-
// CHECK: define{{.*}} ptr @_Z8selfcastP1B(ptr noundef readnone returned %b) local_unnamed_addr
25+
// CHECK: define{{.*}} ptr @_Z8selfcastP1B(ptr noundef readnone returned captures(ret: address, provenance) %b) local_unnamed_addr
2626
// CHECK-NEXT: entry
2727
// CHECK-NEXT: ret ptr %b
2828
// CHECK-NEXT: }
2929

30-
// CHECK: define{{.*}} ptr @_Z9void_castP1B(ptr noundef readonly %b) local_unnamed_addr
30+
// CHECK: define{{.*}} ptr @_Z9void_castP1B(ptr noundef readonly captures(address_is_null, ret: address, provenance) %b) local_unnamed_addr
3131
// CHECK-NEXT: entry:
3232
// CHECK-NEXT: [[isnull:%[0-9]+]] = icmp eq ptr %b, null
3333
// CHECK-NEXT: br i1 [[isnull]], label %[[dynamic_cast_end:[a-z0-9._]+]], label %[[dynamic_cast_notnull:[a-z0-9._]+]]

clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
// CHECK-NEXT: ret ptr @_ZTS1A
2525
// CHECK-NEXT: }
2626

27-
// CHECK: define{{.*}} i1 @_Z5equalP1A(ptr noundef readonly %a) local_unnamed_addr
27+
// CHECK: define{{.*}} i1 @_Z5equalP1A(ptr noundef readonly captures(address_is_null) %a) local_unnamed_addr
2828
// CHECK-NEXT: entry:
2929
// CHECK-NEXT: [[isnull:%[0-9]+]] = icmp eq ptr %a, null
3030
// CHECK-NEXT: br i1 [[isnull]], label %[[bad_typeid:[a-z0-9._]+]], label %[[end:[a-z0-9.+]+]]

clang/test/CodeGenOpenCL/amdgcn-buffer-rsrc-type.cl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ __amdgpu_buffer_rsrc_t getBuffer(void *p) {
2222
}
2323

2424
// CHECK-LABEL: define {{[^@]+}}@consumeBufferPtr
25-
// CHECK-SAME: (ptr addrspace(5) noundef readonly [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
25+
// CHECK-SAME: (ptr addrspace(5) noundef readonly captures(address) [[P:%.*]]) local_unnamed_addr #[[ATTR0]] {
2626
// CHECK-NEXT: entry:
2727
// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq ptr addrspace(5) [[P]], addrspacecast (ptr null to ptr addrspace(5))
2828
// CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
@@ -39,7 +39,7 @@ void consumeBufferPtr(__amdgpu_buffer_rsrc_t *p) {
3939
}
4040

4141
// CHECK-LABEL: define {{[^@]+}}@test
42-
// CHECK-SAME: (ptr addrspace(5) noundef readonly [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
42+
// CHECK-SAME: (ptr addrspace(5) noundef readonly captures(address) [[A:%.*]]) local_unnamed_addr #[[ATTR0]] {
4343
// CHECK-NEXT: entry:
4444
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr addrspace(5) [[A]], align 16, !tbaa [[TBAA8:![0-9]+]]
4545
// CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP0]], 0

clang/test/CodeGenOpenCL/as_type.cl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ int3 f8(char16 x) {
6767
return __builtin_astype(x, int3);
6868
}
6969

70-
//CHECK: define{{.*}} spir_func noundef ptr addrspace(1) @addr_cast(ptr noundef readnone %[[x:.*]])
70+
//CHECK: define{{.*}} spir_func noundef ptr addrspace(1) @addr_cast(ptr noundef readnone captures(ret: address, provenance) %[[x:.*]])
7171
//CHECK: %[[cast:.*]] ={{.*}} addrspacecast ptr %[[x]] to ptr addrspace(1)
7272
//CHECK: ret ptr addrspace(1) %[[cast]]
7373
global int* addr_cast(int *x) {

llvm/include/llvm/Analysis/CaptureTracking.h

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
#define LLVM_ANALYSIS_CAPTURETRACKING_H
1515

1616
#include "llvm/ADT/DenseMap.h"
17+
#include "llvm/Support/ModRef.h"
1718

1819
namespace llvm {
1920

2021
class Value;
2122
class Use;
23+
class CaptureInfo;
2224
class DataLayout;
2325
class Instruction;
2426
class DominatorTree;
@@ -94,31 +96,53 @@ namespace llvm {
9496
/// U->getUser() is always an Instruction.
9597
virtual bool shouldExplore(const Use *U);
9698

97-
/// captured - Information about the pointer was captured by the user of
98-
/// use U. Return true to stop the traversal or false to continue looking
99-
/// for more capturing instructions.
100-
virtual bool captured(const Use *U) = 0;
99+
/// When returned from captures(), stop the traversal.
100+
static std::optional<CaptureComponents> stop() { return std::nullopt; }
101+
102+
/// When returned from captures(), continue traversal, but do not follow
103+
/// the return value of this user, even if it has additional capture
104+
/// components. Should only be used if captures() has already taken the
105+
/// potential return caputres into account.
106+
static std::optional<CaptureComponents> continueIgnoringReturn() {
107+
return CaptureComponents::None;
108+
}
109+
110+
/// When returned from captures(), continue traversal, and also follow
111+
/// the return value of this user if it has additional capture components
112+
/// (that is, capture components in Ret that are not part of Other).
113+
static std::optional<CaptureComponents> continueDefault(CaptureInfo CI) {
114+
CaptureComponents RetCC = CI.getRetComponents();
115+
if (!capturesNothing(RetCC & ~CI.getOtherComponents()))
116+
return RetCC;
117+
return CaptureComponents::None;
118+
}
119+
120+
/// Use U directly captures CI.getOtherComponents() and additionally
121+
/// CI.getRetComponents() through the return value of the user of U.
122+
///
123+
/// Return std::nullopt to stop the traversal, or the CaptureComponents to
124+
/// follow via the return value, which must be a subset of
125+
/// CI.getRetComponents().
126+
///
127+
/// For convenience, prefer returning one of stop(), continueDefault(CI) or
128+
/// continueIgnoringReturn().
129+
virtual std::optional<CaptureComponents> captured(const Use *U,
130+
CaptureInfo CI) = 0;
101131

102132
/// isDereferenceableOrNull - Overload to allow clients with additional
103133
/// knowledge about pointer dereferenceability to provide it and thereby
104134
/// avoid conservative responses when a pointer is compared to null.
105135
virtual bool isDereferenceableOrNull(Value *O, const DataLayout &DL);
106136
};
107137

108-
/// Types of use capture kinds, see \p DetermineUseCaptureKind.
109-
enum class UseCaptureKind {
110-
NO_CAPTURE,
111-
MAY_CAPTURE,
112-
PASSTHROUGH,
113-
};
114-
115138
/// Determine what kind of capture behaviour \p U may exhibit.
116139
///
117-
/// A use can be no-capture, a use can potentially capture, or a use can be
118-
/// passthrough such that the uses of the user or \p U should be inspected.
140+
/// The Other part of the returned CaptureInfo indicates which component of
141+
/// the pointer may be captured directly by the use. The Ret part indicates
142+
/// which components may be captured by following uses of the user of \p U.
119143
/// The \p IsDereferenceableOrNull callback is used to rule out capturing for
120144
/// certain comparisons.
121-
UseCaptureKind
145+
CaptureInfo
122146
DetermineUseCaptureKind(const Use &U,
123147
llvm::function_ref<bool(Value *, const DataLayout &)>
124148
IsDereferenceableOrNull);

llvm/include/llvm/Support/ModRef.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,10 @@ inline bool capturesFullProvenance(CaptureComponents CC) {
309309
return (CC & CaptureComponents::Provenance) == CaptureComponents::Provenance;
310310
}
311311

312+
inline bool capturesAll(CaptureComponents CC) {
313+
return CC == CaptureComponents::All;
314+
}
315+
312316
raw_ostream &operator<<(raw_ostream &OS, CaptureComponents CC);
313317

314318
/// Represents which components of the pointer may be captured in which
@@ -333,6 +337,22 @@ class CaptureInfo {
333337
/// Create CaptureInfo that may capture all components of the pointer.
334338
static CaptureInfo all() { return CaptureInfo(CaptureComponents::All); }
335339

340+
/// Create CaptureInfo that may only capture through means other than the
341+
/// return value.
342+
static CaptureInfo
343+
otherOnly(CaptureComponents OtherComponents = CaptureComponents::All) {
344+
return CaptureInfo(OtherComponents, CaptureComponents::None);
345+
}
346+
347+
/// Create CaptureInfo that may only capture via the return value.
348+
static CaptureInfo
349+
retOnly(CaptureComponents RetComponents = CaptureComponents::All) {
350+
return CaptureInfo(CaptureComponents::None, RetComponents);
351+
}
352+
353+
/// Whether the pointer is only captured via the return value.
354+
bool isRetOnly() const { return capturesNothing(OtherComponents); }
355+
336356
/// Get components potentially captured by the return value.
337357
CaptureComponents getRetComponents() const { return RetComponents; }
338358

0 commit comments

Comments
 (0)