Skip to content

Commit 83de1ef

Browse files
authored
[LangRef] Comment on validity of volatile ops on null (#139803)
Some hardware (for example, certain AVR chips) have peripheral registers mapped to the data space address 0. Although a volatile load/store on `ptr null` already generates expected code, the wording in the LangRef makes operations on null seem like undefined behavior in all cases. This commit adds a comment that, for volatile operations, it may be defined behavior to access the address null, if the architecture permits it. The intended use case is MMIO registers with hard-coded addresses that include bit-value 0. A simple CodeGen test is included for AVR, as an architecture known to have this quirk, that does `load volatile` and `store volatile` to `ptr null`, expecting to generate `lds <reg>, 0` and `sts 0, <reg>`. See [this thread](https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/Adding.20the.20possibility.20of.20volatile.20access.20to.20address.200) and [the RFC](https://discourse.llvm.org/t/rfc-volatile-access-to-non-dereferenceable-memory-may-be-well-defined/86303) for discussion and context.
1 parent 229aa66 commit 83de1ef

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

llvm/docs/LangRef.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3573,7 +3573,8 @@ can read and/or modify state which is not accessible via a regular load
35733573
or store in this module. Volatile operations may use addresses which do
35743574
not point to memory (like MMIO registers). This means the compiler may
35753575
not use a volatile operation to prove a non-volatile access to that
3576-
address has defined behavior.
3576+
address has defined behavior. This includes addresses typically forbidden,
3577+
such as the pointer with bit-value 0.
35773578

35783579
The allowed side-effects for volatile accesses are limited. If a
35793580
non-volatile store to a given address would be legal, a volatile
@@ -4292,7 +4293,10 @@ The semantics of non-zero address spaces are target-specific. Memory
42924293
access through a non-dereferenceable pointer is undefined behavior in
42934294
any address space. Pointers with the bit-value 0 are only assumed to
42944295
be non-dereferenceable in address space 0, unless the function is
4295-
marked with the ``null_pointer_is_valid`` attribute.
4296+
marked with the ``null_pointer_is_valid`` attribute. However, *volatile*
4297+
access to any non-dereferenceable address may have defined behavior
4298+
(according to the target), and in this case the attribute is not needed
4299+
even for address 0.
42964300

42974301
If an object can be proven accessible through a pointer with a
42984302
different address space, the access may be modified to use that
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; RUN: llc < %s -mtriple=avr | FileCheck %s
2+
3+
define i8 @load_volatile_null() {
4+
; CHECK-LABEL: load_volatile_null:
5+
; CHECK: lds r24, 0
6+
%result = load volatile i8, ptr null
7+
ret i8 %result
8+
}
9+
10+
define void @store_volatile_null(i8 %a) {
11+
; CHECK-LABEL: store_volatile_null:
12+
; CHECK: sts 0, r24
13+
store volatile i8 %a, ptr null
14+
ret void
15+
}

0 commit comments

Comments
 (0)