Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion llvm/docs/LangRef.md
Original file line number Diff line number Diff line change
Expand Up @@ -2658,7 +2658,8 @@ fn -> other_fn -> other_fn ; fn is norecurse
how much of the frame is cleared:

- `"used"` clears every stack slot the function used.
- `"sensitive"` clears the slots that sensitivity metadata identifies,
- `"sensitive"` clears the slots that
{ref}`sensitivity metadata <md_sensitive>` identifies,
together with every slot whose contents cannot be traced back to a
source-level object. The second half is not optional: spill slots, the
callee-save area, and alignment padding can all hold copies of data that
Expand Down Expand Up @@ -8012,6 +8013,57 @@ call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) %d,
!"nvvm.l2_prefetch_size", !"128B" }
```

(md_sensitive)=

#### '`sensitive`' Metadata

`sensitive` metadata may be attached to an `alloca` to record that the object
it allocates holds data that should not be left readable in the stack frame
once the function is done with it. It identifies the objects that the
`"sensitive"` mode of the `"zeroize-stack"` function attribute clears.

This metadata is only used as a flag, so the associated node must be empty. Its
presence on the `alloca` is the entire signal; the contents of the node are
reserved for future use.

```llvm
%round_keys = alloca [176 x i8], align 16, !sensitive !0

...
!0 = !{}
```

The metadata is a hint that lets a function clear less of its frame than it
would otherwise have to. It is not itself part of any guarantee, and no
guarantee is conditioned on it being present, accurate, or complete. The
obligation to clear a frame comes from the `"zeroize-stack"` attribute alone,
and the `"sensitive"` mode of that attribute clears every frame object whose
contents cannot be traced back to a source-level object — spill slots, the
callee-save area, alignment padding — whether or not anything is marked.

Transforms must respect the one-directional rule this sets up:

- Dropping the metadata is always permitted. A transform is never required to
preserve or propagate it in order to be correct, and no correctness argument
may rest on it having survived. Where the marked set has stopped describing
the frame, because a marked object was split, merged, replaced, or promoted
and the metadata did not follow, the response is to clear more, falling back
at the limit to clearing every stack slot the function used. It is never to
clear less.
- Attaching the metadata to an object that was not marked before is likewise
permitted, and can only widen what is cleared.
- The absence of the metadata on a frame object is not a statement that the
object is insensitive. A transform may not conclude from an object being
unmarked that its contents need not be cleared, and may not shrink the set of
objects a function clears on the strength of what is or is not marked.
Clearing only the marked objects together with the objects of unknown
provenance is the request that the `"sensitive"` mode expresses; it is not a
licence for a transform to narrow that set further.

Whether an individual transform propagates this metadata across the objects it
creates is therefore a question of precision rather than of correctness, and is
specified separately.

(llvm.loop)=

#### '`llvm.loop`'
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/IR/FixedMetadataKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ LLVM_FIXED_MD_KIND(MD_mem_cache_hint, "mem.cache_hint", 52)
LLVM_FIXED_MD_KIND(MD_block_uniformity_profile, "block.uniformity.profile", 53)
LLVM_FIXED_MD_KIND(MD_callgraph, "callgraph", 54)
LLVM_FIXED_MD_KIND(MD_metadata_section_kind, "metadata_section_kind", 55)
LLVM_FIXED_MD_KIND(MD_sensitive, "sensitive", 56)
31 changes: 31 additions & 0 deletions llvm/test/Assembler/sensitive-metadata.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
; Textual and bitcode round-trips of !sensitive on an alloca.
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s

define void @marked() {
; CHECK-LABEL: define void @marked() {
; CHECK-NEXT: [[ROUND_KEYS:%.*]] = alloca [176 x i8], align 16, !sensitive [[META0:![0-9]+]]
; CHECK-NEXT: ret void
;
%round_keys = alloca [176 x i8], align 16, !sensitive !0
ret void
}

; The metadata is a flag, so every marked object shares the one empty node.
define void @marked_twice() {
; CHECK-LABEL: define void @marked_twice() {
; CHECK-NEXT: [[KEY:%.*]] = alloca i64, align 8, !sensitive [[META0]]
; CHECK-NEXT: [[NONCE:%.*]] = alloca i64, align 8, !sensitive [[META0]]
; CHECK-NEXT: [[SCRATCH:%.*]] = alloca i64, align 8
; CHECK-NEXT: ret void
;
%key = alloca i64, align 8, !sensitive !0
%nonce = alloca i64, align 8, !sensitive !0
%scratch = alloca i64, align 8
ret void
}

!0 = !{}
;.
; CHECK: [[META0]] = !{}
;.