vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
//! Declarative operation specifications.
//!
//! The operation layer is the vocabulary of vyre. Every op is either a
//! Category A composition (pure IR that lowers to exactly what a human
//! shader author would write) or a Category C hardware intrinsic (requires
//! a specific backend feature). This module defines the metadata that
//! frontends consume, the conform gate verifies, and backends lower.
//!
//! WGSL is a lowering artifact produced by [`crate::lower`], never by an
//! operation definition. Operations declare semantics, not target code.

use crate::ir::{DataType, Program};

mod metadata;

/// Algebraic laws declared by an operation (commutativity, associativity, etc.).
///
/// Laws are not decorative: the conform gate verifies them against the CPU
/// reference and rejects any backend that produces a counterexample.
pub use vyre_spec::AlgebraicLaw;

/// Short alias for [`AlgebraicLaw`] used in operation tables.

/// Operation metadata emitted by the build-time `spec.toml` walker.
///
/// This module is generated at compile time by `vyre-build-scan`. It
/// contains a flat table of every operation discovered in the repository,
/// which the conform gate uses to certify backends.
pub mod discovered {
    include!(concat!(env!("OUT_DIR"), "/walked_ops.rs"));
}

/// CPU reference execution traits.
///
/// Every registered operation must provide a pure-Rust CPU reference so
/// that the conform gate can prove byte-identicality against any backend.
pub mod cpu_op;

/// Re-export of the CPU operation traits.
///
/// `CpuOp` is the trait for operations that can run on the CPU reference.
/// `CategoryAOp` marks compositional operations that lower entirely to IR.
pub use cpu_op::{CategoryAOp, CpuOp};
pub use metadata::{Backend, Category, Compose, IntrinsicDescriptor};

/// Declarative operation specification.
///
/// `OpSpec` is the metadata contract for every operation in vyre. It
/// declares the op's ID, category, type signature, algebraic laws, and
/// implementation. Frontends read specs to emit calls; the conform gate
/// reads specs to verify correctness.
#[non_exhaustive]
#[derive(Debug, Clone, Copy)]
pub struct OpSpec {
    id: &'static str,
    category: Category,
    inputs: &'static [DataType],
    outputs: &'static [DataType],
    laws: &'static [AlgebraicLaw],
    inlinable: bool,
    compose: Compose,
}

impl OpSpec {
    /// Create a Category A composition specification.
    ///
    /// Use this constructor for operations that are pure IR compositions
    /// and must be dispatched as separate kernels.
    ///
    /// # Examples
    ///
    /// ```
    /// use vyre::ops::OpSpec;
    /// use vyre::ir::{DataType, Program};
    /// use vyre::ops::AlgebraicLaw;
    ///
    /// fn build_program() -> Program {
    ///     Program::new(vec![], [1, 1, 1], vec![])
    /// }
    ///
    /// let spec = OpSpec::composition(
    ///     "primitive.arith.add",
    ///     &[DataType::U32, DataType::U32],
    ///     &[DataType::U32],
    ///     &[AlgebraicLaw::Commutative],
    ///     build_program,
    /// );
    ///
    /// assert_eq!(spec.id(), "primitive.arith.add");
    /// ```
    #[must_use]
    pub const fn composition(
        id: &'static str,
        inputs: &'static [DataType],
        outputs: &'static [DataType],
        laws: &'static [AlgebraicLaw],
        compose: fn() -> Program,
    ) -> Self {
        Self {
            id,
            category: Category::A,
            inputs,
            outputs,
            laws,
            inlinable: false,
            compose: Compose::Composition(compose),
        }
    }

    /// Create a Category A composition that may be expanded from `Expr::Call`.
    ///
    /// Inlinable compositions can be substituted directly into the caller's
    /// IR body, eliminating a separate kernel dispatch. The conform gate
    /// verifies that the inlined output is byte-identical to the
    /// stand-alone composition.
    ///
    /// # Examples
    ///
    /// ```
    /// use vyre::ops::OpSpec;
    /// use vyre::ir::{DataType, Program};
    ///
    /// fn build_program() -> Program {
    ///     Program::new(vec![], [1, 1, 1], vec![])
    /// }
    ///
    /// let spec = OpSpec::composition_inlinable(
    ///     "primitive.bitwise.xor",
    ///     &[DataType::U32, DataType::U32],
    ///     &[DataType::U32],
    ///     &[],
    ///     build_program,
    /// );
    ///
    /// assert!(spec.inlinable());
    /// ```
    #[must_use]
    pub const fn composition_inlinable(
        id: &'static str,
        inputs: &'static [DataType],
        outputs: &'static [DataType],
        laws: &'static [AlgebraicLaw],
        compose: fn() -> Program,
    ) -> Self {
        Self {
            id,
            category: Category::A,
            inputs,
            outputs,
            laws,
            inlinable: true,
            compose: Compose::Composition(compose),
        }
    }

    /// Create a Category C intrinsic specification.
    ///
    /// Use this constructor for hardware-dependent operations that have no
    /// software fallback. The `backend_availability` predicate must return
    /// `false` for any backend that lacks the required feature.
    ///
    /// # Examples
    ///
    /// ```
    /// use vyre::ops::{OpSpec, Backend, IntrinsicDescriptor};
    /// use vyre::ir::DataType;
    ///
    /// fn always(_: &Backend) -> bool { true }
    /// fn dummy(_input: &[u8], _output: &mut Vec<u8>) {}
    ///
    /// let spec = OpSpec::intrinsic(
    ///     "primitive.hw.magic",
    ///     &[DataType::U32],
    ///     &[DataType::U32],
    ///     &[],
    ///     always,
    ///     IntrinsicDescriptor::new("magic", "magic_hw", dummy),
    /// );
    ///
    /// assert!(spec.available_on(&Backend::Wgsl));
    /// ```
    #[must_use]
    pub const fn intrinsic(
        id: &'static str,
        inputs: &'static [DataType],
        outputs: &'static [DataType],
        laws: &'static [AlgebraicLaw],
        backend_availability: fn(&Backend) -> bool,
        intrinsic: IntrinsicDescriptor,
    ) -> Self {
        Self {
            id,
            category: Category::C {
                backend_availability,
            },
            inputs,
            outputs,
            laws,
            inlinable: false,
            compose: Compose::Intrinsic(intrinsic),
        }
    }

    /// Stable hierarchical operation id.
    ///
    /// The ID is the primary key in the operation registry and appears in
    /// conform certificates, KAT tables, and frontend call sites.
    #[must_use]
    pub const fn id(&self) -> &'static str {
        self.id
    }

    /// Operation category.
    ///
    /// Category determines whether the op is a compositional IR body
    /// (Category A) or a hardware intrinsic (Category C).
    #[must_use]
    pub const fn category(&self) -> Category {
        self.category
    }

    /// Input data types.
    ///
    /// These types describe the logical input buffers or scalar arguments
    /// that the operation expects.
    #[must_use]
    pub const fn inputs(&self) -> &'static [DataType] {
        self.inputs
    }

    /// Output data types.
    ///
    /// These types describe the logical output buffers or scalar results
    /// that the operation produces.
    #[must_use]
    pub const fn outputs(&self) -> &'static [DataType] {
        self.outputs
    }

    /// Declared algebraic laws.
    ///
    /// The conform gate verifies every declared law against the CPU
    /// reference. A law violation produces a concrete counterexample and
    /// blocks backend certification.
    #[must_use]
    pub const fn laws(&self) -> &'static [AlgebraicLaw] {
        self.laws
    }

    /// Whether this operation may be expanded from `Expr::Call`.
    ///
    /// Inlinable ops eliminate kernel-dispatch overhead when they are
    /// composed into larger programs.
    #[must_use]
    pub const fn inlinable(&self) -> bool {
        self.inlinable
    }

    /// Composition or intrinsic implementation descriptor.
    ///
    /// This is the implementation payload that lowering uses to generate
    /// target code.
    #[must_use]
    pub const fn compose(&self) -> Compose {
        self.compose
    }

    /// Build the operation program when this is Category A.
    ///
    /// Returns `None` for Category C intrinsics because they do not have
    /// an IR composition; they map directly to backend-specific hardware
    /// instructions.
    ///
    /// # Examples
    ///
    /// ```
    /// use vyre::ops::OpSpec;
    /// use vyre::ir::{DataType, Program};
    ///
    /// fn build_program() -> Program {
    ///     Program::new(vec![], [1, 1, 1], vec![])
    /// }
    ///
    /// let spec = OpSpec::composition(
    ///     "demo.op",
    ///     &[],
    ///     &[],
    ///     &[],
    ///     build_program,
    /// );
    ///
    /// assert!(spec.program().is_some());
    /// ```
    #[must_use]
    pub fn program(&self) -> Option<Program> {
        match self.compose {
            Compose::Composition(build) => Some(build().with_entry_op_id(self.id)),
            Compose::Intrinsic(_) => None,
        }
    }

    /// Return whether this op can run on `backend`.
    ///
    /// Category A ops are always available. Category C ops are available
    /// only when the backend's predicate returns `true`.
    ///
    /// # Examples
    ///
    /// ```
    /// use vyre::ops::{OpSpec, Backend};
    /// use vyre::ir::{DataType, Program};
    ///
    /// fn build_program() -> Program {
    ///     Program::new(vec![], [1, 1, 1], vec![])
    /// }
    ///
    /// let spec = OpSpec::composition(
    ///     "demo.op",
    ///     &[],
    ///     &[],
    ///     &[],
    ///     build_program,
    /// );
    ///
    /// assert!(spec.available_on(&Backend::Wgsl));
    /// ```
    #[must_use]
    pub fn available_on(&self, backend: &Backend) -> bool {
        match self.category {
            Category::A => true,
            Category::C {
                backend_availability,
            } => backend_availability(backend),
        }
    }
}

/// Type signature constant: single `Bytes` input.
pub const BYTES_TO_BYTES_INPUTS: &[DataType] = &[DataType::Bytes];
/// Type signature constant: single `Bytes` output.
pub const BYTES_TO_BYTES_OUTPUTS: &[DataType] = &[DataType::Bytes];
/// Type signature constant: single `U32` output from `Bytes` input.
pub const BYTES_TO_U32_OUTPUTS: &[DataType] = &[DataType::U32];
/// Type signature constant: single `U32` input.
pub const U32_INPUTS: &[DataType] = &[DataType::U32];
/// Type signature constant: pair of `U32` inputs.
pub const U32_U32_INPUTS: &[DataType] = &[DataType::U32, DataType::U32];
/// Type signature constant: single `U32` output.
pub const U32_OUTPUTS: &[DataType] = &[DataType::U32];
/// Type signature constant: single `F32` input.
pub const F32_INPUTS: &[DataType] = &[DataType::F32];
/// Type signature constant: pair of `F32` inputs.
pub const F32_F32_INPUTS: &[DataType] = &[DataType::F32, DataType::F32];
/// Type signature constant: three `F32` inputs.
pub const F32_F32_F32_INPUTS: &[DataType] = &[DataType::F32, DataType::F32, DataType::F32];
/// Type signature constant: single `F32` output.
pub const F32_OUTPUTS: &[DataType] = &[DataType::F32];
/// Type signature constant: single `I32` output.
pub const I32_OUTPUTS: &[DataType] = &[DataType::I32];
/// Type signature constant: single `Bool` output.
pub const BOOL_OUTPUTS: &[DataType] = &[DataType::Bool];

// Operation category sub-modules.
/// Buffer layout and access operations.
pub mod buffer;
/// Compression and decompression operations.
pub mod compression;
/// Cryptographic primitive operations.
pub mod crypto;
/// Data movement and copy operations.
pub mod data_movement;
/// Decode pipeline operations (base64, hex, url, unicode).
pub mod decode;
/// Encode pipeline operations.
pub mod encode;
/// Graph construction and traversal operations.
pub mod graph;
/// Hashing operations.
pub mod hash;
/// Match extraction and filtering operations.
pub mod match_ops;
/// Primitive arithmetic, logical, and bitwise operations.
pub mod primitive;
/// Reduction operations (sum, min, max, etc.).
pub mod reductions;
/// Operation registry and discovery.
pub mod registry;
/// Rule formula construction and evaluation.
pub mod rule;
/// Scanning and pattern matching operations.
pub mod scan;
/// Security detection operations.
pub mod security_detection;
/// Sorting operations.
pub mod sort;
/// Statistical operations.
pub mod stats;
/// String manipulation operations.
pub mod string;
/// String matching operations.
pub mod string_matching;
/// String similarity operations.
pub mod string_similarity;
/// Workgroup-shared memory and synchronization operations.
pub mod workgroup;

/// Shared test fixtures for operation KATs (available only under `#[cfg(test)]`).
#[cfg(test)]
pub mod fixtures;