-
Notifications
You must be signed in to change notification settings - Fork 57
Structure of a Jasmin program
A Jasmin program is a collection of:
- parameters;
- global variables;
- functions.
Since version 2022.04.0, a program may be split into several files using a
require
clause. Its simplest form is as follows
require "path/file.jinc"
Relative paths are resolved relative to the current file.
The required file is treated (mostly) as if its contents were put in place of the require
clause.
Files can also be searched in named locations, for instance:
from AES require "aes.jinc"
This clause requires the file aes.jinc
that is located in a path named AES
.
There are two ways to give names to paths in the file-system:
- either on the command-line using the argument
-I AES:actual/path/
; - or using the
JASMINPATH
environment variable, as inexport JASMINPATH=AES=actual/path/
.
If several paths must be named, the -I
argument can be used multiple times, and in the environment variable value,
several ID=path
pairs can be separated by a colon (:
).
A parameter is a named value. The name can be used within types (e.g., as the size of an array): as such, they can be used to provide a limited form of genericity.
Parameters are removed by the compiler right after parsing; in particular, they do not appear in the Coq abstract syntax. Therefore, they have no formal semantics.
A parameter is introduced by the param
keyword, followed by a type, a name, and the value.
For instance:
param int cROUNDS = 2;
Jasmin compiler latest development version (still unreleased) introduced a new syntax feature for type definition. A type alias can be defined at top level of a program or a namespace. The aim of this feature is to improve genericity of Jasmin code. The types aliases are resolved like params, during parsing.
To define a type alias, we introduced the type
keyword, which is followed by a name, and the a type. For example :
type reg_size = u64;
Defined types can then be used in programs in place of the compiler types.
reg reg_size a; //declaring variable a with type reg_size
reg reg_size[10] b; //declaring an array with elements of type reg_size
We can note that the feature doesn't allow definitions like :
type x = reg u64;
We can consider that the storage type (reg
, stack
, inline
...) is similar to the declaration keyword let
in other languages (for instance Rust). Storage type is thus not a type, and should not be aliased.
A global variable is a named valued. Unlike parameters, said value is not available at compile-time (i.e., it cannot be used as part of a type), but it is available at run-time.
Technically, global variables are stored in the code segment and are accessed to using PC-relative addressing mode.
There is no keyword to introduce a global variable declaration at the top-level, only its type, name, and value. For instance:
u128 rotate24pattern = (16u8)[ 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 ];
In this example, the value is a 128-bit machine-word, described as a vector of 16 8-bit machine-words.
A function is introduced using the fn
keyword, followed by the function name,
the list of its parameters, its return type (if any), and its body.
The body begins with the declaration of local variables and ends with a return
statement.
Here is an example function:
inline
fn shift(reg u128 x, inline int count) -> reg u128 {
reg u128 r;
r = #VPSLL_4u32(x, count);
return r;
}
A function definition may be prefixed with either the inline
keyword or the export
keyword
to denote, respectively, that the function will be removed by the compiler or that it will be present in
the final assembly code and respect the target calling conventions.
Functions that are not marked with inline
or export
are local functions:
they will be preserved by the compiler but are not visible from the outside
(i.e, they cannot be called from non-Jasmin code). This feature has been
introduced in version 2022.04.0.