Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4ba4b87

Browse files
committedNov 26, 2024·
Add address_is_null capture component
1 parent a5fd333 commit 4ba4b87

File tree

8 files changed

+42
-24
lines changed

8 files changed

+42
-24
lines changed
 

‎llvm/docs/LangRef.rst

+6-16
Original file line numberDiff line numberDiff line change
@@ -1388,10 +1388,11 @@ Currently, only the following parameter attributes are defined:
13881388
which may be ``none``, or a combination of:
13891389

13901390
- ``address``: The integral address of the pointer.
1391+
- ``address_is_null`` (subet of ``address``): Whether the address is null.
13911392
- ``provenance``: The ability to access the pointer for both read and write
13921393
after the function returns.
1393-
- ``read_provenance``: The ability to access the pointer only for reads
1394-
after the function returns.
1394+
- ``read_provenance`` (subset of ``provenance``): The ability to access the
1395+
pointer only for reads after the function returns.
13951396

13961397
Additionally, it is possible to specify that the pointer is captured via
13971398
the return value only, by using ``captures(ret: ...)``.
@@ -1404,6 +1405,7 @@ Currently, only the following parameter attributes are defined:
14041405
- ``captures(none)``: Pointer not captured.
14051406
- ``captures(address, provenance)``: Equivalent to omitting the attribute.
14061407
- ``captures(address)``: Address may be captured, but not provenance.
1408+
- ``captures(address_is_null)``: Only captures whether the address is null.
14071409
- ``captures(address, read_provenance)``: Both address and provenance
14081410
captured, but only for read-only access.
14091411
- ``captures(ret: address, provenance)``: Pointer captured through return
@@ -3352,7 +3354,8 @@ memory before the call, the call may capture two components of the pointer:
33523354

33533355
* The address of the pointer, which is its integral value. This also includes
33543356
parts of the address or any information about the address, including the
3355-
fact that it does not equal one specific value.
3357+
fact that it does not equal one specific value. We further distinguish
3358+
whether only the fact that the address is/isn't null is captured.
33563359
* The provenance of the pointer, which is the ability to perform memory
33573360
accesses through the pointer, in the sense of the :ref:`pointer aliasing
33583361
rules <pointeraliasing>`. We further distinguish whether only read acceses
@@ -3400,19 +3403,6 @@ function, provenance capture refers exclusively to the ability to perform
34003403
accesses *after* the function returns. Memory accesses within the function
34013404
itself are not considered pointer captures.
34023405

3403-
Comparison of a pointer with a null pointer is generally also considered an
3404-
address capture. As an exception, if the pointer is known to be either null
3405-
or in bounds of an allocated object, it is not considered an address capture.
3406-
As such, the following example does not capture the pointer argument due to
3407-
the presence of the ``dereferenceable_or_null`` attribute:
3408-
3409-
.. code-block:: llvm
3410-
3411-
define i1 @f(ptr dereferenceable_or_null(4) %a) {
3412-
%c = icmp eq ptr %a, null
3413-
ret i1 %c
3414-
}
3415-
34163406
We can further say that the capture only occurs through a specific location.
34173407
In the following example, the pointer (both address and provenance) is captured
34183408
through the return value only:

‎llvm/include/llvm/AsmParser/LLToken.h

+1
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ enum Kind {
209209

210210
// Captures attribute:
211211
kw_address,
212+
kw_address_is_null,
212213
kw_provenance,
213214
kw_read_provenance,
214215

‎llvm/include/llvm/Support/ModRef.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -276,9 +276,10 @@ using FunctionModRefBehavior = MemoryEffects;
276276
/// Components of the pointer that may be captured.
277277
enum class CaptureComponents : uint8_t {
278278
None = 0,
279-
Address = (1 << 0),
280-
ReadProvenance = (1 << 1),
281-
Provenance = (1 << 2) | ReadProvenance,
279+
AddressIsNull = (1 << 0),
280+
Address = (1 << 1) | AddressIsNull,
281+
ReadProvenance = (1 << 2),
282+
Provenance = (1 << 3) | ReadProvenance,
282283
All = Address | Provenance,
283284
LLVM_MARK_AS_BITMASK_ENUM(Provenance),
284285
};
@@ -291,6 +292,10 @@ inline bool capturesAnything(CaptureComponents CC) {
291292
return CC != CaptureComponents::None;
292293
}
293294

295+
inline bool capturesAddressIsNullOnly(CaptureComponents CC) {
296+
return (CC & CaptureComponents::Address) == CaptureComponents::AddressIsNull;
297+
}
298+
294299
inline bool capturesAddress(CaptureComponents CC) {
295300
return (CC & CaptureComponents::Address) != CaptureComponents::None;
296301
}

‎llvm/lib/AsmParser/LLLexer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,7 @@ lltok::Kind LLLexer::LexIdentifier() {
704704
KEYWORD(argmemonly);
705705
KEYWORD(inaccessiblememonly);
706706
KEYWORD(inaccessiblemem_or_argmemonly);
707+
KEYWORD(address_is_null);
707708
KEYWORD(address);
708709
KEYWORD(provenance);
709710
KEYWORD(read_provenance);

‎llvm/lib/AsmParser/LLParser.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -3192,15 +3192,17 @@ bool LLParser::parseCapturesAttr(AttrBuilder &B) {
31923192
return true;
31933193
} else {
31943194
while (true) {
3195-
if (EatIfPresent(lltok::kw_address))
3195+
if (EatIfPresent(lltok::kw_address_is_null))
3196+
CC |= CaptureComponents::AddressIsNull;
3197+
else if (EatIfPresent(lltok::kw_address))
31963198
CC |= CaptureComponents::Address;
31973199
else if (EatIfPresent(lltok::kw_provenance))
31983200
CC |= CaptureComponents::Provenance;
31993201
else if (EatIfPresent(lltok::kw_read_provenance))
32003202
CC |= CaptureComponents::ReadProvenance;
32013203
else
3202-
return tokError(
3203-
"expected one of 'address', 'provenance' or 'read_provenance'");
3204+
return tokError("expected one of 'address', 'address_is_null', "
3205+
"'provenance' or 'read_provenance'");
32043206

32053207
if (EatIfPresent(lltok::rparen))
32063208
break;

‎llvm/lib/Support/ModRef.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, CaptureComponents CC) {
5959
}
6060

6161
ListSeparator LS;
62-
if (capturesAddress(CC))
62+
if (capturesAddressIsNullOnly(CC))
63+
OS << LS << "address_is_null";
64+
else if (capturesAddress(CC))
6365
OS << LS << "address";
6466
if (capturesReadProvenanceOnly(CC))
6567
OS << LS << "read_provenance";

‎llvm/test/Assembler/captures-errors.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ define void @test(ptr captures(ret address) %p) {
3535

3636
;--- invalid-component.ll
3737

38-
; CHECK-INVALID-COMPONENT: <stdin>:[[@LINE+1]]:32: error: expected one of 'address', 'provenance' or 'read_provenance'
38+
; CHECK-INVALID-COMPONENT: <stdin>:[[@LINE+1]]:32: error: expected one of 'address', 'address_is_null', 'provenance' or 'read_provenance'
3939
define void @test(ptr captures(foo) %p) {
4040
ret void
4141
}

‎llvm/test/Assembler/captures.ll

+17
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ define void @test_address(ptr captures(address) %p) {
1818
ret void
1919
}
2020

21+
define void @test_address_is_null(ptr captures(address_is_null) %p) {
22+
; CHECK-LABEL: define void @test_address_is_null(
23+
; CHECK-SAME: ptr captures(address_is_null) [[P:%.*]]) {
24+
; CHECK-NEXT: ret void
25+
;
26+
ret void
27+
}
28+
2129
define void @test_address_provenance(ptr captures(address, provenance) %p) {
2230
; CHECK-LABEL: define void @test_address_provenance(
2331
; CHECK-SAME: ptr captures(address, provenance) [[P:%.*]]) {
@@ -60,6 +68,15 @@ define void @test_duplicate_read_provenance(ptr captures(read_provenance, proven
6068
ret void
6169
}
6270

71+
; address_is_null is a subset of address.
72+
define void @test_duplicate_address_is_null(ptr captures(address_is_null, address) %p) {
73+
; CHECK-LABEL: define void @test_duplicate_address_is_null(
74+
; CHECK-SAME: ptr captures(address) [[P:%.*]]) {
75+
; CHECK-NEXT: ret void
76+
;
77+
ret void
78+
}
79+
6380
; Return-only none is same as plain none.
6481
define void @test_ret_none(ptr captures(ret: none) %p) {
6582
; CHECK-LABEL: define void @test_ret_none(

0 commit comments

Comments
 (0)
Please sign in to comment.