Packages
orb
0.0.23
0.2.2
0.2.1
0.2.0
0.1.1
0.1.0
0.0.51
0.0.49
0.0.48
0.0.47
0.0.46
0.0.45
0.0.44
0.0.43
0.0.42
0.0.41
0.0.40
0.0.39
0.0.38
0.0.37
0.0.36
0.0.35
0.0.34
0.0.33
0.0.32
0.0.31
0.0.30
0.0.28
0.0.27
0.0.26
0.0.25
0.0.24
0.0.23
0.0.22
0.0.21
0.0.20
0.0.19
0.0.18
0.0.17
0.0.16
0.0.15
0.0.14
0.0.13
0.0.12
retired
0.0.11
0.0.10
0.0.9
0.0.8
0.0.7
0.0.6
0.0.5
0.0.4
0.0.3
0.0.2
0.0.1
DSL for WebAssembly
Current section
Files
Jump to
Current section
Files
lib/orb/memory.ex
defmodule Orb.Memory do
@moduledoc """
Work with memory.
"""
defstruct name: "", min: 0, exported?: false
@doc false
def from(_)
def from(nil), do: nil
def from([]), do: nil
def from(list) when is_list(list) do
case Enum.sum(list) do
0 ->
nil
min ->
%__MODULE__{min: min}
end
end
@page_byte_size 64 * 1024
def page_byte_size(), do: @page_byte_size
@doc """
Declare how many 64Kib pages of memory your module needs.
Can be called multiple times, with each summed up.
Returns the previous page count, which can be used as a start offset.
"""
defmacro pages(page_count) do
quote do
start_offset = Enum.sum(@wasm_memory)
@wasm_memory unquote(page_count)
start_offset
end
end
@doc "Initializes data in memory. In Wat is `(data …)`"
def initial_data(offset: offset, string: value) do
%Orb.Data{offset: offset, value: value, nul_terminated: false}
end
@doc "Initializes data in memory from a packed `Map`. In Wat is `(data …)`"
def initial_data_prepacked(packed_map) when is_map(packed_map) do
for {_key, %{offset: offset, string: string}} <- packed_map do
initial_data(offset: offset, string: string)
end
end
@doc """
Load value of `type` from memory `address`.
```elixir
Memory.load!(I32, 0x100)
Memory.load!(I32.U8, 0x100)
```
"""
def load!(type, address) do
Code.ensure_loaded!(type)
primitive_type =
if function_exported?(type, :wasm_type, 0) do
type.wasm_type()
else
raise "You passed a Orb type module #{type} that does not implement wasm_type/0."
end
load_instruction =
if function_exported?(type, :load_instruction, 0) do
type.load_instruction()
else
:load
end
Orb.Instruction.new(primitive_type, load_instruction, [address])
end
@doc """
Store `value` of `type` at memory `address`.
```elixir
Memory.store!(I32, 0x100, 42)
Memory.store!(I32.U8, 0x100, ?a)
```
"""
def store!(type, address, value) do
Code.ensure_loaded!(type)
primitive_type =
if function_exported?(type, :wasm_type, 0) do
type.wasm_type()
else
raise "You passed a Orb type module #{type} that does not implement wasm_type/0."
end
load_instruction =
if function_exported?(type, :load_instruction, 0) do
type.load_instruction()
else
:load
end
store_instruction =
case load_instruction do
:load8_u -> :store8
:load8_s -> :store8
:load -> :store
end
Orb.Instruction.new(primitive_type, store_instruction, [address, value])
end
defimpl Orb.ToWat do
def to_wat(%Orb.Memory{min: min}, indent) do
[
indent,
~S{(memory (export "memory")},
case min do
nil -> []
int -> [" ", to_string(int)]
end,
~S{)},
"\n"
]
end
end
end