This document describes storage classes in CSL.Documentation Index
Fetch the complete documentation index at: https://sdk.cerebras.ai/llms.txt
Use this file to discover all available pages before exploring further.
Overview
By default, any variable declared in a CSL program is accessible only within the program itself. This means that when linking two separately-compiled objectsA and B, variables declared in the source code for A will
not be visible in the source code for B, and vice versa. It also means
that tools manipulating symbols in the compiled binary (such as readelf or
the Cerebras ELFLoader class in Python) will not necessarily be able to
access the contents of the symbol by name.
CSL features two storage classes for global variables and functions that modify
this default behavior: extern and export.
extern
Theextern storage class declares that a symbol for a variable or function,
with a certain type, is expected to be defined in an export declaration
elsewhere. That export declaration may either be in the object file
currently being compiled, or in another object file that will be linked with
the object being compiled. Declaring a variable with extern makes that
variable or function available for use within the current source file, under
the declared name.
A variable declaration with the extern storage class must not have an
initializer expression, and a function declaration with the extern storage
class must not have a body block.
Declarations with extern storage must have export-compatible types. See
Type restrictions for more details.
Currently, no calling convention for extern functions is formally defined.
Calling extern functions at comptime is not allowed.
Examples:
export
Theexport storage class defines a variable or function with a certain
name and type, and makes that variable or function available to other object
files that are linked with the object being compiled.
A variable declaration with the export storage class may have an
initializer expression, but it is not required. A function declaration with
the export storage class must have a body block.
Declarations with export storage must have export-compatible types. See
Type restrictions for more details.
Currently, no calling convention for export functions is formally defined.
In addition to making symbols accessible by other objects, export ensures
that the symbol will be accessible via the Python ELFLoader class (or
other tools that operate on ELF files). If a symbol is intended to be accessed
either in the compiled binary or in a post-execution core dump via
ELFLoader, that symbol must be declared export.
Examples:
Object file symbols for extern and export declarations
Unless a linkname is supplied (see below), the symbol name for an
export or extern declaration will be the same as its CSL variable
name, even if the variable is declared inside an imported module.
Additionally, export or extern symbols will be part of a single
global namespace shared with all other objects with which the compiled object
is linked. For example:
Interaction with linkname
Both export and extern declarations may be assigned a linkname.
If a linkname is present, that name is used for the symbol in the object
file. For example:
export declarations are present in code that is
intended to be imported with @import_module. Here, comptime determination
of the linkname can be used to avoid clashes among symbol names. For
example:
Mixing extern and export declarations
It is legal to have multiple extern declarations with the same object
symbol name within a compiled program, and up to one export declaration,
as long as all declarations sharing a symbol name agree on declaration kind
(var, const, or fn) and have the same type. Neither an extern
nor an export declaration may share a symbol name with a declaration that
has no storage class (i.e., one which is neither export nor extern).
For example:
Type restrictions
Declarations withexport or extern storage class must have a type that
is export compatible.
For variable declarations, export compatibility is defined as follows:
- Fixed-width integer types are export compatible when they are ABI-sized.
16-bit and 32-bit integers (
i16,i32,u16, andu32) are ABI-sized and therefore export compatible. - All DSD types except FIFOs are export compatible.
- The built-in types
@fp16(),f32,bool, andcolorare export compatible. Note that@fp16()gives the type of the selected runtime FP16 format (see @fp16). - An array type of the form
[N]Tis export compatible if its base typeTis export compatible. - A pointer type of the form
*Tor*const Tis export compatible if its base type is export compatible. - Function pointers are a special case: a pointer type of the form
*const T, whereTis a function type, is export compatible ifTis export compatible for a function declaration (see below). (Theconstqualifier is required.) enumtypes are export compatible if their underlying integer type is export compatible.extern structandextern uniontypes are export compatible.packed structandpacked uniontypes are export compatible when their backing integers are ABI-sized.
struct and union types
without extern or packed, the direction type, the range type, void
(except in function return type position–see below), and function types (as
opposed to function pointer types) are not export compatible.
For function declarations, export compatibility is defined as follows:
- A function type of the form
fn(t1, t2, ..., tn) tis export compatible if all of its argument types (t1, t2, ..., tn) are export compatible for variable declarations (see above) and are allowed for CSL function arguments, and its return typeteither is export compatible and allowed for CSL function return types, or isvoid.
extern or export functions.
