Files
Odin/examples/runtime.odin
T
2016-08-19 23:35:09 +01:00

177 lines
4.3 KiB
Odin

putchar :: proc(c: i32) -> i32 #foreign
mem_compare :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcmp"
mem_copy :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memcpy"
mem_move :: proc(dst, src : rawptr, len: int) -> i32 #foreign "memmove"
debug_trap :: proc() #foreign "llvm.debugtrap"
// TODO(bill): make custom heap procedures
heap_realloc :: proc(ptr: rawptr, sz: int) -> rawptr #foreign "realloc"
heap_alloc :: proc(sz: int) -> rawptr { return heap_realloc(null, sz); }
heap_free :: proc(ptr: rawptr) { _ = heap_realloc(ptr, 0); }
__string_eq :: proc(a, b : string) -> bool {
if len(a) != len(b) {
return false;
}
if ^a[0] == ^b[0] {
return true;
}
return mem_compare(^a[0], ^b[0], len(a)) == 0;
}
__string_ne :: proc(a, b : string) -> bool {
return !__string_eq(a, b);
}
__string_cmp :: proc(a, b : string) -> int {
min_len := len(a);
if len(b) < min_len {
min_len = len(b);
}
for i := 0; i < min_len; i++ {
x := a[i];
y := b[i];
if x < y {
return -1;
} else if x > y {
return +1;
}
}
if len(a) < len(b) {
return -1;
} else if len(a) > len(b) {
return +1;
}
return 0;
}
__string_lt :: proc(a, b : string) -> bool { return __string_cmp(a, b) < 0; }
__string_gt :: proc(a, b : string) -> bool { return __string_cmp(a, b) > 0; }
__string_le :: proc(a, b : string) -> bool { return __string_cmp(a, b) <= 0; }
__string_ge :: proc(a, b : string) -> bool { return __string_cmp(a, b) >= 0; }
type AllocationMode: int;
ALLOCATION_ALLOC :: 0;
ALLOCATION_DEALLOC :: 1;
ALLOCATION_DEALLOC_ALL :: 2;
ALLOCATION_RESIZE :: 3;
type AllocatorProc: proc(allocator_data: rawptr, mode: AllocationMode,
size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
type Allocator: struct {
procedure: AllocatorProc,
data: rawptr,
}
type Context: struct {
thread_id: i32,
user_index: i32,
user_data: rawptr,
allocator: Allocator,
}
#thread_local context: Context;
DEFAULT_ALIGNMENT :: 2*size_of(int);
__check_context :: proc() {
if context.allocator.procedure == null {
context.allocator = __default_allocator();
}
ptr := __check_context as rawptr;
}
alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); }
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
__check_context();
a := context.allocator;
return a.procedure(a.data, ALLOCATION_ALLOC, size, alignment, null, 0, 0);
}
dealloc :: proc(ptr: rawptr) #inline {
__check_context();
a := context.allocator;
_ = a.procedure(a.data, ALLOCATION_DEALLOC, 0, 0, ptr, 0, 0);
}
dealloc_all :: proc(ptr: rawptr) #inline {
__check_context();
a := context.allocator;
_ = a.procedure(a.data, ALLOCATION_DEALLOC_ALL, 0, 0, ptr, 0, 0);
}
resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); }
resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
__check_context();
a := context.allocator;
return a.procedure(a.data, ALLOCATION_RESIZE, new_size, alignment, ptr, old_size, 0);
}
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
if old_memory == null {
return alloc_align(new_size, alignment);
}
if new_size == 0 {
dealloc(old_memory);
return null;
}
if new_size < old_size {
new_size = old_size;
}
if old_size == new_size {
return old_memory;
}
new_memory := alloc_align(new_size, alignment);
if new_memory == null {
return null;
}
_ = copy((new_memory as ^u8)[:new_size], (old_memory as ^u8)[:old_size]);
dealloc(old_memory);
return new_memory;
}
__default_allocator_proc :: proc(allocator_data: rawptr, mode: AllocationMode,
size, alignment: int,
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
if mode == ALLOCATION_ALLOC {
return heap_alloc(size);
} else if mode == ALLOCATION_RESIZE {
return heap_realloc(old_memory, size);
} else if mode == ALLOCATION_DEALLOC {
heap_free(old_memory);
} else if mode == ALLOCATION_DEALLOC_ALL {
// NOTE(bill): Does nothing
}
return null;
}
__default_allocator :: proc() -> Allocator {
return Allocator{
__default_allocator_proc,
null,
};
}