Wasm allocator?

Is there one available?

I have been using this in C: malloc0/malloc0.c at main · muayyad-alsadi/malloc0 · GitHub

But i have trouble trying to port it to odin, can anyone help?

Here what i got so far:


@(default_calling_convention = "c")
foreign _ {
    update_memory_view::proc() ---
}


import "base:intrinsics"



__heap_tail:uint;
__heap_mark:uint;
__mi:bool

@(default_calling_convention = "c")
foreign _ {
    __heap_base: u8
}

_mem_alignment :: 4
_size_t_bytes :: 4
_mem_flag_used :: 0xbf82583a
_mem_flag_free :: 0xab34d705
page_alloc :: proc(page_count: int) -> (data: []byte, err: mem.Allocator_Error) {
	prev_page_count := intrinsics.wasm_memory_grow(0, uintptr(page_count))

    if !__mi {
        __heap_tail = transmute(uint) transmute(^uint) &__heap_base
        __heap_mark = transmute(uint) transmute(^uint) &__heap_base
        __mi = true
    }
    n := uint(page_count)

    n += (8 - (n % _mem_alignment)) % _mem_alignment
    // check if size is enough
    total :uint= uint(__heap_tail) + n + 3*_size_t_bytes
    size :uint=auto_cast intrinsics.wasm_memory_size(0)<<16
    if total > size {
        ignore := intrinsics.wasm_memory_grow(0, auto_cast ((total>>16)-(size>>16)+1) )
        update_memory_view()
    }
    r :=  transmute(uint) __heap_tail
    (transmute(^uint)r)^ =n
    r+= _size_t_bytes;
    (transmute(^uint)r)^ =_mem_flag_used
    r+= _size_t_bytes
    __heap_tail = r + n
    (transmute(^uint)__heap_tail)^ = n
    __heap_tail += _size_t_bytes



    ret:= transmute([^]u8) r;

    return ret[0:page_count], .None
}

page_free::proc(p: rawptr) -> (err: mem.Allocator_Error) {

    n: uint
    if p == nil {
        return .None
    }

    r := transmute(uint) p

    r -= _size_t_bytes

    if (transmute(^uint) r)^ != _mem_flag_used {
        return .None
    }

    flag: uint = _mem_flag_free

    (transmute(^uint) r)^ = flag

    r -= _size_t_bytes

    n = (transmute(^uint)r)^

    ptr_tail := (transmute(uint)p) + n + _size_t_bytes

    if __heap_tail != ptr_tail {
        return .None
    }

    __heap_tail = r

    for(r > transmute(uint)&__heap_base) {
        r -= _size_t_bytes
        n = (transmute(^uint)r)^
        r -= n
        r -= _size_t_bytes
        flag = (transmute(^uint)r)^
        if flag != _mem_flag_free {
            break
        }
        r -= _size_t_bytes
        n = (transmute(^uint) r)^
        __heap_tail = r
    }

    return .None
}


page_realloc::proc(p: rawptr, old_size, new_size: int) -> (data: []byte, err: mem.Allocator_Error)
{
    if p == nil {
        return page_alloc(new_size)
    }

    ret, e :=page_alloc(new_size)

    oldBytes :[]byte= ([^]byte)(p)[:old_size]

    for it, i in oldBytes {
        ret[i] = it
    }

    ignore := page_free(p)

    return ret, e
}

page_allocator :: proc() -> mem.Allocator {
	procedure :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
	                  size, alignment: int,
	                  old_memory: rawptr, old_size: int,
	                  location := #caller_location) -> ([]byte, mem.Allocator_Error) {
		#partial switch mode {
		case .Alloc, .Alloc_Non_Zeroed:
			return page_alloc(size)
		case .Resize:
            return page_realloc(old_memory, old_size, size)

        case.Free:
            return nil, page_free(old_memory)

		case .Query_Features:
			set := (^mem.Allocator_Mode_Set)(old_memory)
			if set != nil {
				set^ = {.Alloc, .Free, .Resize, .Query_Features}
			}
		}

		return nil, nil
	}

	return {
		procedure = procedure,
		data = nil,
	}
}

Odin has a default one for the wasm platforms based on the old emscripten one. It’s the default context.allocator.

See: Odin/base/runtime/wasm_allocator.odin at master · odin-lang/Odin · GitHub

Wow, i wonder how i missed this one, thanks, i’ll take a look