Skip to content

Commit

Permalink
wasm: implement inline assembly (#19686)
Browse files Browse the repository at this point in the history
  • Loading branch information
l1mey112 committed Oct 29, 2023
1 parent 705eea8 commit c32b04d
Show file tree
Hide file tree
Showing 17 changed files with 1,419 additions and 105 deletions.
2 changes: 1 addition & 1 deletion vlib/builtin/wasm/alloc.v
Expand Up @@ -4,7 +4,7 @@ module builtin
// Shitty `sbrk` basic `malloc` and `free` impl
// TODO: implement pure V `walloc` later

__global g_heap_base = usize(__heap_base())
__global g_heap_base = usize(vwasm_heap_base())

// malloc dynamically allocates a `n` bytes block of memory on the heap.
// malloc returns a `byteptr` pointing to the memory address of the allocated space.
Expand Down
90 changes: 69 additions & 21 deletions vlib/builtin/wasm/builtin.v
@@ -1,24 +1,41 @@
module builtin

fn __heap_base() voidptr
fn __memory_size() usize
fn __memory_grow(size usize) usize
fn __memory_fill(dest &u8, value isize, size isize)
fn __memory_copy(dest &u8, src &u8, size isize)

// add doc comments for the below functions

// __reinterpret_f32_u32 converts a `u32` to a `f32` without changing the bit pattern.
pub fn __reinterpret_f32_u32(v f32) u32

// __reinterpret_u32_f32 converts a `f32` to a `u32` without changing the bit pattern.
pub fn __reinterpret_u32_f32(v u32) f32
// vwasm_heap_base returns the base address of the heap.
pub fn vwasm_heap_base() voidptr {
mut rval := unsafe { nil }
asm wasm {
global.get __heap_base
local.set rval
; =r (rval)
}
return rval
}

// __reinterpret_f64_u64 converts a `u64` to a `f64` without changing the bit pattern.
pub fn __reinterpret_f64_u64(v f64) u64
// vwasm_heap_size returns the size of the main wasm memory in pages.
// Analagous to the `memory.size` instruction.
pub fn vwasm_memory_size() int {
mut rval := 0
asm wasm {
memory.size
local.set rval
; =r (rval)
}
return rval
}

// __reinterpret_u64_f64 converts a `f64` to a `u64` without changing the bit pattern.
pub fn __reinterpret_u64_f64(v u64) f64
// vwasm_memory_grow grows the main wasm memory by `size` pages.
// Analagous to the `memory.grow` instruction.
pub fn vwasm_memory_grow(size int) int {
mut rval := 0
asm wasm {
local.get size
memory.grow
local.set rval
; =r (rval)
; r (size)
}
return rval
}

// vcalloc dynamically allocates a zeroed `n` bytes block of memory on the heap.
// vcalloc returns a `byteptr` pointing to the memory address of the allocated space.
Expand All @@ -33,7 +50,14 @@ pub fn vcalloc(n isize) &u8 {

res := unsafe { malloc(n) }

__memory_fill(res, 0, n)
asm wasm {
local.get res
i32.const 0x0
local.get n
memory.fill
; ; r (res)
r (n)
}

return res
}
Expand All @@ -48,22 +72,46 @@ pub fn isnil(v voidptr) bool {
// The memory areas **CAN** overlap. vmemcpy returns a pointer to `dest`.
[unsafe]
pub fn vmemcpy(dest voidptr, const_src voidptr, n isize) voidptr {
__memory_copy(dest, const_src, n)
asm wasm {
local.get dest
local.get const_src
local.get n
memory.copy
; ; r (dest)
r (const_src)
r (n)
}
return dest
}

// vmemmove copies n bytes from memory area src to memory area dest.
// The memory areas **CAN** overlap. vmemmove returns a pointer to `dest`.
[unsafe]
pub fn vmemmove(dest voidptr, const_src voidptr, n isize) voidptr {
__memory_copy(dest, const_src, n)
asm wasm {
local.get dest
local.get const_src
local.get n
memory.copy
; ; r (dest)
r (const_src)
r (n)
}
return dest
}

// vmemset fills the first `n` bytes of the memory area pointed to by `s`,
// with the constant byte `c`. It returns a pointer to the memory area `s`.
[unsafe]
pub fn vmemset(s voidptr, c int, n isize) voidptr {
__memory_fill(s, c, n)
asm wasm {
local.get s
local.get c
local.get n
memory.fill
; ; r (s)
r (c)
r (n)
}
return s
}
3 changes: 3 additions & 0 deletions vlib/v/ast/ast.v
Expand Up @@ -2411,6 +2411,9 @@ pub fn all_registers(mut t Table, arch pref.Arch) map[string]ScopeObject {
res[k] = v
}
}
.wasm32 {
// no registers
}
else { // TODO
panic('all_registers: unhandled arch')
}
Expand Down
9 changes: 7 additions & 2 deletions vlib/v/fmt/asm.v
Expand Up @@ -12,7 +12,12 @@ fn (mut f Fmt) asm_stmt(stmt ast.AsmStmt) {
} else if stmt.is_goto {
f.write('goto ')
}
f.writeln('${stmt.arch} {')
lit_arch := if stmt.arch == .wasm32 {
'wasm'
} else {
stmt.arch.str()
}
f.writeln('${lit_arch} {')
f.indent++

f.asm_templates(stmt.templates)
Expand Down Expand Up @@ -54,7 +59,7 @@ fn (mut f Fmt) asm_arg(arg ast.AsmArg) {
f.write(arg.val.str())
}
string {
f.write(arg)
f.string_literal(ast.StringLiteral{ val: arg })
}
ast.AsmAddressing {
if arg.segment != '' {
Expand Down

0 comments on commit c32b04d

Please sign in to comment.