Tensor materials and operation preparation
A material is Tensor data referenced by a Program symbol. Compilation.material_bindings maps those symbols to live Tensors, including evaluation keys, RNS parameters, NTT tables, codec tables, and mutable rounding state. Preparation declares missing operands and optionally obtains data from caller-supplied providers before execution is linked.
What is data, and what is an execution handle?
| Representation | Stored value | Owner |
|---|---|---|
MaterialRefOp and Compilation.material_bindings | Numerical Tensor | Compilation and caller's Tensor ownership |
Program.material_descriptions | Optional description of a material's purpose | Program metadata used for inspection and preparation |
ResourceRefOp and ResourceRequirement | Symbol and kind of a non-Tensor execution handle | IR or selected implementation |
BackendWorkspace.named_resources | BoundResource values with symbol, kind, and live object | Backend workspace |
BackendWorkspace.materializer | Optional constructor of missing execution handles | Backend workspace |
Process groups and encryption samplers are execution handles. RNS parameter arrays and evaluation-key payloads are numerical data even when they are long-lived or expensive to construct. BackendWorkspace contains named handles and an optional handle materializer; the Tensor binding dictionary belongs to Compilation.
How do material references enter a Program?
Capture retains actual Tensor objects from values, keys, and tables. It does not copy their contents. Lowering can introduce additional MaterialRefOp operands when it exposes arithmetic previously hidden inside a whole operation. compile/_materials.py allocates symbols and attaches optional descriptions without renumbering existing references.
Descriptions can record material kind, key role, algorithm-table layout, or parameter identity. They support optional data selection. A directly supplied binding remains the caller's assignment; descriptions guide optional selection without inspecting or overwriting that data.
ResolveTensorPlaceholdersPass reads the current binding dictionary and propagates available physical facts into placeholder types. It performs no key generation or provider invocation. A Program can retain missing bindings during inspection and transformation; linking requires every material that the executable references.
What does operand preparation add?
PrepareOperationOperandsPass asks a selected implementation's optional tensor_requirements(operation, config) for required attributes and named material descriptions. It adds missing Tensor operands while preserving supplied operands, existing symbols, and implementation assignments. The callback can defer when configuration, placement, or algorithm constraints are insufficient.
This mechanism applies to retained native whole operations as well as newly exposed lower-level operations. For example, a whole key switch needs its internal NTT schedule and parameter/table operands. A lowered key switch separates RNS ModUp and ModDown tables from the selected logical NTT operations' table requirements. RNS-only preparation can use RnsContext; transform tables require a compatible NTT provider and layout.
SelectNttImplementationsPass selects missing schedules under existing constraints and declares corresponding table references. Supplied table operands remain dataflow inputs. Selecting a compact radix-2 group width can reuse the compatible compact table layout; incompatible layouts must not be silently substituted.
How does optional data provision work?
prepare_material_bindings(compilation, resources=..., keys=...) fills only absent entries and returns the symbols still unresolved. Resources can be existing CkksDeviceResources, RnsContext, or NttContext providers. Keys can be supplied as named entries, an iterable of key values, or an EvaluationKeySet.
Named key entries matching a material symbol or label assign data directly. Semantic selection from supplied candidates succeeds only when one distinct Tensor candidate matches the description; absent or ambiguous candidates remain unresolved. Existing bindings are not inspected or overwritten. No evaluation keys are generated by this utility.
The following helper demonstrates caller-owned preparation of an existing Compilation:
from fhelium import compile as fc
def supply_materials(compilation, *, resources=(), keys=()):
unresolved = fc.prepare_material_bindings(
compilation, resources=resources, keys=keys
)
return unresolved2
3
4
5
6
7
Providers may construct or retrieve the numerical tables requested by this preparation step. Material-table lookup subsequently returns the supplied Tensor. The default lowering-and-fusion recipe invokes operand preparation with supplied providers before dependent selection and again after lowerings expose new operands.
What remains live after linking?
Linking resolves references to Tensor objects and builds a host callable retaining those objects. Replacing compilation.material_bindings[symbol] later does not rebind an existing executable; relink to use the replacement. In-place writes to the bound Tensor remain visible because linking did not snapshot its contents.
Layout-specialized execution still requires its prepared shape, stride, dtype, extent, and placement contract. Mutating storage structure is different from updating compatible contents. Synchronization with active device work or concurrent writers remains the caller's responsibility.
Mutable rounding streams are numerical Tensor state with effects. Encryption's sampler is a live handle with effects. Preparation must not replace either with one frozen random sample. Saving selected bindings can capture sensitive or mutable data; see Compilation persistence for inclusion and security semantics.
Extension points
An implementation that needs numerical operands can declare tensor_requirements and consume the resulting Tensors through the ordinary execution interface. Place table construction beside the numerical owner, such as backend/rns/tables.py or backend/ntt/tables.py. Use resource_requirements only for genuine non-Tensor handles. Registration and selection describes how implementations enter the registry, and prepared host execution describes final linking.