From 6a5db03ae485daced634d365610ef96da295079e Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Fri, 19 Jun 2026 17:10:06 +0200 Subject: [PATCH] Metal: mark by-reference kernel arguments read-only `add_argument_metadata!` tagged every buffer argument `air.read_write`, but by-reference arguments (the kernel state, bitstype objects passed by pointer) are loaded into a stack slot at function entry and never written back through the argument pointer -- any device pointers they contain address separate, independently-bound buffers. Tagging them `air.read` lets a host bind them with read-only data (Metal's `setBytes:`) without API validation rejecting read-only bytes bound to a write-accessible argument. Genuine pointer-to-data arguments (`Ptr`/`LLVMPtr` bound to a real buffer) stay read-write. Co-Authored-By: Claude Opus 4.8 (1M context) --- Project.toml | 2 +- src/metal.jl | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index f5d149d82..9f7141743 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "GPUCompiler" uuid = "61eb1bfa-7361-4325-ad38-22787b887f55" -version = "1.22.1" +version = "1.22.2" authors = ["Tim Besard "] [workspace] diff --git a/src/metal.jl b/src/metal.jl index 5107b02ab..dc6f32ed3 100644 --- a/src/metal.jl +++ b/src/metal.jl @@ -1270,7 +1270,13 @@ function add_argument_metadata!(@nospecialize(job::CompilerJob), mod::LLVM.Modul # XXX: unknown push!(md, Metadata(ConstantInt(Int32(1)))) - push!(md, MDString("air.read_write")) # TODO: Check for const array + # only pointer-to-data arguments are written through; by-reference values (kernel + # state, bitstype objects) are read into a stack slot and never written back. + if arg.cc == BITS_VALUE && (arg.typ <: Ptr || arg.typ <: Core.LLVMPtr) + push!(md, MDString("air.read_write")) + else + push!(md, MDString("air.read")) + end push!(md, MDString("air.address_space")) push!(md, Metadata(ConstantInt(Int32(addrspace(parameters(entry_ft)[arg.idx])))))