Inline Assembly
Introduction
Inline assembly in Wave is written with asm {... It is written within a }` block.
Within Wave code, you can directly control registers, memory, and system call paths.
Currently supported targets:
- Linux
x86_64 - Linux
aarch64 - macOS (Darwin)
arm64 - freestanding
x86_64 - freestanding
aarch64 - freestanding
riscv64
Windows and 32-bit targets are not supported yet.
Basic Form
asm can be used both as a statement and as an expression.
asm {
"instruction"
in("constraint_or_reg") value
out("constraint_or_reg") target
clobber("item")
}
Components:
- String line: actual assembly instruction
in(...): input operandsout(...): output operandsclobber(...): hints for clobbered registers/status/memory
asm Statement
It is used as a regular statement if no return value is needed.
var ret: i64 = 0;
asm {
"mov rax, 1"
"syscall"
in("rdi") 1
in("rsi") msg_ptr
in("rdx") 20
out("rax") ret
}
Multiple out(...) can be used.
asm Expression
It can be used as an expression that directly generates a value.
var result: i64 = asm {
"mov rax, 123"
out("rax") result
};
Caution:
asmexpressions allow exactly 1out(...).
in(...) / out(...) Constraints
The strings for in("..."), out("...") are one of the following.
- Specific Registers
- Example:
"rax","rdi","x0","w1","a0","t0","x10"
- Constraint Class
- Examples:
"r","m","rm"
Example:
in("r") &buf
out("rax") ret
Output Target (out(...) target) the following pattern is recommended based on current implementation.
- Variable:
out("rax") ret - Pointer dereference:
out("rax") deref p
clobber(...)
clobber(...) can take multiple items at once, and can be used multiple times.
asm {
"xor rax, rax"
clobber("rax")
clobber("rcx", "rdx")
clobber("memory")
}
Key Items:
- Registers:
"rax","x0", etc. - Special:
"memory","cc"(internally normalized per target)
The compiler automatically adds default clobbers in conservative safety mode.
(memory, flags/cc family, etc.; primarily memory for RISC-V freestanding)
Operand placeholders ($0, $1, ...)
Use $N to refer to operands within a command string.
asm {
"mov QWORD PTR [$0], 777"
in("r") &buf
clobber("memory")
}
Note:
- Even if
%0style is used, it is internally converted to$0style.
Current support range for input operands
in(...) values currently support the following forms.
- Variable identifier
- Integer literal
- String literal
&identifierderef identifier- Negative integer/real literal
Complex general expressions may be restricted, so it is recommended to store them in temporary variables for transmission when necessary.
Precautions
Inline assembly partially bypasses the protection of the type system. Incorrect register specification, constraint conflicts, and missing clobbers can cause incorrect code generation or runtime malfunctions.
Recommendations:
- First finalize the target ABI and calling conventions
- Explicitly manage input/output registers and clobbers
- Declare
clobber("memory")when directly touching memory