
This introduces the `captures` attribute as described in: https://discourse.llvm.org/t/rfc-improvements-to-capture-tracking/81420 This initial patch only introduces the IR/bitcode support for the attribute and its in-memory representation as `CaptureInfo`. This will be followed by a patch to upgrade and remove the `nocapture` attribute, and then by actual inference/analysis support. Based on the RFC feedback, I've used a syntax similar to the `memory` attribute, though the only "location" that can be specified is `ret`. I've added some pretty extensive documentation to LangRef on the semantics. One non-obvious bit here is that using ptrtoint will not result in a "return-only" capture, even if the ptrtoint result is only used in the return value. Without this requirement we wouldn't be able to continue ordinary capture analysis on the return value.
104 lines
2.9 KiB
LLVM
104 lines
2.9 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: opt -S < %s | FileCheck %s
|
|
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
|
|
|
|
define void @test_none(ptr captures(none) %p) {
|
|
; CHECK-LABEL: define void @test_none(
|
|
; CHECK-SAME: ptr captures(none) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
define void @test_address(ptr captures(address) %p) {
|
|
; CHECK-LABEL: define void @test_address(
|
|
; CHECK-SAME: ptr captures(address) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
define void @test_address_is_null(ptr captures(address_is_null) %p) {
|
|
; CHECK-LABEL: define void @test_address_is_null(
|
|
; CHECK-SAME: ptr captures(address_is_null) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
define void @test_address_provenance(ptr captures(address, provenance) %p) {
|
|
; CHECK-LABEL: define void @test_address_provenance(
|
|
; CHECK-SAME: ptr captures(address, provenance) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
define void @test_address_read_provenance(ptr captures(address, read_provenance) %p) {
|
|
; CHECK-LABEL: define void @test_address_read_provenance(
|
|
; CHECK-SAME: ptr captures(address, read_provenance) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
define void @test_ret(ptr captures(ret: address, provenance) %p) {
|
|
; CHECK-LABEL: define void @test_ret(
|
|
; CHECK-SAME: ptr captures(ret: address, provenance) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
define void @test_address_is_null_and_ret(ptr captures(address_is_null, ret: address, provenance) %p) {
|
|
; CHECK-LABEL: define void @test_address_is_null_and_ret(
|
|
; CHECK-SAME: ptr captures(address_is_null, ret: address, provenance) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
define void @test_address_and_ret_none(ptr captures(address, ret: none) %p) {
|
|
; CHECK-LABEL: define void @test_address_and_ret_none(
|
|
; CHECK-SAME: ptr captures(address, ret: none) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
; Duplicates callpse into one.
|
|
define void @test_duplicate(ptr captures(address, address) %p) {
|
|
; CHECK-LABEL: define void @test_duplicate(
|
|
; CHECK-SAME: ptr captures(address) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
; read_provenance is a subset of provenance.
|
|
define void @test_duplicate_read_provenance(ptr captures(read_provenance, provenance) %p) {
|
|
; CHECK-LABEL: define void @test_duplicate_read_provenance(
|
|
; CHECK-SAME: ptr captures(provenance) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
; address_is_null is a subset of address.
|
|
define void @test_duplicate_address_is_null(ptr captures(address_is_null, address) %p) {
|
|
; CHECK-LABEL: define void @test_duplicate_address_is_null(
|
|
; CHECK-SAME: ptr captures(address) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|
|
|
|
; Return-only none is same as plain none.
|
|
define void @test_ret_none(ptr captures(ret: none) %p) {
|
|
; CHECK-LABEL: define void @test_ret_none(
|
|
; CHECK-SAME: ptr captures(none) [[P:%.*]]) {
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
ret void
|
|
}
|