mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-28 18:30:06 +00:00
Add Pointer Arithmetic
This commit is contained in:
+10
-8
@@ -31,6 +31,7 @@ Type_Info :: union {
|
||||
Float: struct #ordered {
|
||||
size: int // in bytes
|
||||
}
|
||||
Any: struct #ordered {}
|
||||
String: struct #ordered {}
|
||||
Boolean: struct #ordered {}
|
||||
Pointer: struct #ordered {
|
||||
@@ -142,7 +143,7 @@ __check_context :: proc() {
|
||||
c := ^__context
|
||||
|
||||
if c.allocator.procedure == nil {
|
||||
c.allocator = __default_allocator()
|
||||
c.allocator = default_allocator()
|
||||
}
|
||||
if c.thread_id == 0 {
|
||||
c.thread_id = os.current_thread_id()
|
||||
@@ -173,6 +174,7 @@ free_all :: proc() #inline {
|
||||
|
||||
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, Allocator.Mode.RESIZE, new_size, alignment, ptr, old_size, 0)
|
||||
}
|
||||
@@ -204,16 +206,16 @@ default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment:
|
||||
}
|
||||
|
||||
|
||||
__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||
default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||
using Allocator.Mode
|
||||
match mode {
|
||||
case ALLOC:
|
||||
total_size := size + alignment + size_of(mem.AllocationHeader)
|
||||
ptr := os.heap_alloc(total_size)
|
||||
header := ptr as ^mem.AllocationHeader
|
||||
ptr = mem.align_forward(ptr_offset(header, 1), alignment)
|
||||
ptr = mem.align_forward(header+1, alignment)
|
||||
mem.allocation_header_fill(header, ptr, size)
|
||||
return mem.zero(ptr, size)
|
||||
|
||||
@@ -228,7 +230,7 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
||||
total_size := size + alignment + size_of(mem.AllocationHeader)
|
||||
ptr := os.heap_resize(mem.allocation_header(old_memory), total_size)
|
||||
header := ptr as ^mem.AllocationHeader
|
||||
ptr = mem.align_forward(ptr_offset(header, 1), alignment)
|
||||
ptr = mem.align_forward(header+1, alignment)
|
||||
mem.allocation_header_fill(header, ptr, size)
|
||||
return mem.zero(ptr, size)
|
||||
}
|
||||
@@ -236,9 +238,9 @@ __default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator.Mode,
|
||||
return nil
|
||||
}
|
||||
|
||||
__default_allocator :: proc() -> Allocator {
|
||||
default_allocator :: proc() -> Allocator {
|
||||
return Allocator{
|
||||
procedure = __default_allocator_proc,
|
||||
procedure = default_allocator_proc,
|
||||
data = nil,
|
||||
}
|
||||
}
|
||||
|
||||
+45
-89
@@ -50,8 +50,7 @@ print_byte_buffer :: proc(buf: ^[]byte, b: []byte) {
|
||||
if buf.count < buf.capacity {
|
||||
n := min(buf.capacity-buf.count, b.count)
|
||||
if n > 0 {
|
||||
offset := ptr_offset(buf.data, buf.count)
|
||||
mem.copy(offset, ^b[0], n)
|
||||
mem.copy(buf.data + buf.count, ^b[0], n)
|
||||
buf.count += n
|
||||
}
|
||||
}
|
||||
@@ -77,64 +76,8 @@ print_rune_to_buffer :: proc(buf: ^[]byte, r: rune) {
|
||||
print_space_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune " ") }
|
||||
print_nl_to_buffer :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune "\n") }
|
||||
|
||||
print_int_to_buffer :: proc(buf: ^[]byte, i: int) {
|
||||
print_int_base_to_buffer(buf, i, 10);
|
||||
}
|
||||
|
||||
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
|
||||
|
||||
print_int_base_to_buffer :: proc(buffer: ^[]byte, i, base: int) {
|
||||
|
||||
buf: [65]byte
|
||||
len := 0
|
||||
negative := false
|
||||
if i < 0 {
|
||||
negative = true
|
||||
i = -i
|
||||
}
|
||||
if i == 0 {
|
||||
buf[len] = #rune "0"
|
||||
len++
|
||||
}
|
||||
for i > 0 {
|
||||
buf[len] = __NUM_TO_CHAR_TABLE[i % base]
|
||||
len++
|
||||
i /= base
|
||||
}
|
||||
|
||||
if negative {
|
||||
buf[len] = #rune "-"
|
||||
len++
|
||||
}
|
||||
|
||||
byte_reverse(buf[:len])
|
||||
print_string_to_buffer(buffer, buf[:len] as string)
|
||||
}
|
||||
|
||||
print_uint_to_buffer :: proc(buffer: ^[]byte, i: uint) {
|
||||
print_uint_base_to_buffer(buffer, i, 10, 0, #rune " ")
|
||||
}
|
||||
print_uint_base_to_buffer :: proc(buffer: ^[]byte, i, base: uint, min_width: int, pad_char: byte) {
|
||||
buf: [65]byte
|
||||
len := 0
|
||||
if i == 0 {
|
||||
buf[len] = #rune "0"
|
||||
len++
|
||||
}
|
||||
for i > 0 {
|
||||
buf[len] = __NUM_TO_CHAR_TABLE[i % base]
|
||||
len++
|
||||
i /= base
|
||||
}
|
||||
for len < min_width {
|
||||
buf[len] = pad_char
|
||||
len++
|
||||
}
|
||||
|
||||
byte_reverse(buf[:len])
|
||||
print_string_to_buffer(buffer, buf[:len] as string)
|
||||
}
|
||||
|
||||
print_bool_to_buffer :: proc(buffer: ^[]byte, b : bool) {
|
||||
if b { print_string_to_buffer(buffer, "true") }
|
||||
else { print_string_to_buffer(buffer, "false") }
|
||||
@@ -142,7 +85,7 @@ print_bool_to_buffer :: proc(buffer: ^[]byte, b : bool) {
|
||||
|
||||
print_pointer_to_buffer :: proc(buffer: ^[]byte, p: rawptr) #inline {
|
||||
print_string_to_buffer(buffer, "0x")
|
||||
print_uint_base_to_buffer(buffer, p as uint, 16, size_of(int), #rune "0")
|
||||
print_u64_to_buffer(buffer, p as uint as u64)
|
||||
}
|
||||
|
||||
print_f32_to_buffer :: proc(buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7) }
|
||||
@@ -215,7 +158,7 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||
} else {
|
||||
print_string_to_buffer(buf, "u")
|
||||
}
|
||||
print_int_to_buffer(buf, 8*info.size)
|
||||
print_u64_to_buffer(buf, 8*info.size as u64)
|
||||
}
|
||||
|
||||
case Float:
|
||||
@@ -267,7 +210,7 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||
|
||||
case Array:
|
||||
print_string_to_buffer(buf, "[")
|
||||
print_int_to_buffer(buf, info.count)
|
||||
print_i64_to_buffer(buf, info.count as i64)
|
||||
print_string_to_buffer(buf, "]")
|
||||
print_type_to_buffer(buf, info.elem)
|
||||
case Slice:
|
||||
@@ -276,7 +219,7 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||
print_type_to_buffer(buf, info.elem)
|
||||
case Vector:
|
||||
print_string_to_buffer(buf, "{")
|
||||
print_int_to_buffer(buf, info.count)
|
||||
print_i64_to_buffer(buf, info.count as i64)
|
||||
print_string_to_buffer(buf, "}")
|
||||
print_type_to_buffer(buf, info.elem)
|
||||
|
||||
@@ -327,6 +270,13 @@ print_type_to_buffer :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||
}
|
||||
|
||||
|
||||
make_any :: proc(type_info: ^Type_Info, data: rawptr) -> any {
|
||||
a: any
|
||||
a.type_info = type_info
|
||||
a.data = data
|
||||
return a
|
||||
}
|
||||
|
||||
print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
if arg.type_info == nil {
|
||||
print_string_to_buffer(buf, "<nil>")
|
||||
@@ -347,12 +297,11 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
if i > 0 {
|
||||
print_string_to_buffer(buf, ", ")
|
||||
}
|
||||
print_any_to_buffer(buf, f.name)
|
||||
print_string_to_buffer(buf, f.name)
|
||||
// print_any_to_buffer(buf, f.offset)
|
||||
print_string_to_buffer(buf, " = ")
|
||||
v: any
|
||||
v.type_info = f.type_info
|
||||
v.data = ptr_offset(arg.data as ^byte, f.offset)
|
||||
print_any_to_buffer(buf, v)
|
||||
data := arg.data as ^byte + f.offset
|
||||
print_any_to_buffer(buf, make_any(f.type_info, data))
|
||||
}
|
||||
print_string_to_buffer(buf, "}")
|
||||
|
||||
@@ -421,10 +370,12 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
}
|
||||
|
||||
case Maybe:
|
||||
if arg.data != nil {
|
||||
// TODO(bill): print maybe
|
||||
size := mem.size_of_type_info(info.elem)
|
||||
data := slice_ptr(arg.data as ^byte, size+1)
|
||||
if data[size] != 0 && arg.data != nil {
|
||||
print_any_to_buffer(buf, make_any(info.elem, arg.data))
|
||||
} else {
|
||||
print_string_to_buffer(buf, "<nil>")
|
||||
print_string_to_buffer(buf, "nil")
|
||||
}
|
||||
|
||||
case Enum:
|
||||
@@ -463,10 +414,8 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
print_string_to_buffer(buf, ", ")
|
||||
}
|
||||
|
||||
elem: any
|
||||
elem.data = (arg.data as int + i*info.elem_size) as rawptr
|
||||
elem.type_info = info.elem
|
||||
print_any_to_buffer(buf, elem)
|
||||
data := arg.data as ^byte + i*info.elem_size
|
||||
print_any_to_buffer(buf, make_any(info.elem, data))
|
||||
}
|
||||
|
||||
case Slice:
|
||||
@@ -479,25 +428,35 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
print_string_to_buffer(buf, ", ")
|
||||
}
|
||||
|
||||
elem: any
|
||||
elem.data = ptr_offset(slice.data, i*info.elem_size)
|
||||
elem.type_info = info.elem
|
||||
print_any_to_buffer(buf, elem)
|
||||
data := slice.data + i*info.elem_size
|
||||
print_any_to_buffer(buf, make_any(info.elem, data))
|
||||
}
|
||||
|
||||
case Vector:
|
||||
is_bool :: proc(type_info: ^Type_Info) -> bool {
|
||||
match type info : type_info {
|
||||
case Named:
|
||||
return is_bool(info.base)
|
||||
case Boolean:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
print_string_to_buffer(buf, "<")
|
||||
defer print_string_to_buffer(buf, ">")
|
||||
|
||||
if is_bool(info.elem) {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < info.count; i++ {
|
||||
if i > 0 {
|
||||
print_string_to_buffer(buf, ", ")
|
||||
}
|
||||
|
||||
elem: any
|
||||
elem.data = ptr_offset(arg.data as ^byte, i*info.elem_size)
|
||||
elem.type_info = info.elem
|
||||
print_any_to_buffer(buf, elem)
|
||||
data := arg.data as ^byte + i*info.elem_size
|
||||
print_any_to_buffer(buf, make_any(info.elem, data))
|
||||
}
|
||||
|
||||
|
||||
@@ -510,12 +469,11 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
if i > 0 {
|
||||
print_string_to_buffer(buf, ", ")
|
||||
}
|
||||
print_any_to_buffer(buf, info.fields[i].name)
|
||||
print_string_to_buffer(buf, info.fields[i].name)
|
||||
print_string_to_buffer(buf, " = ")
|
||||
a: any
|
||||
a.data = ptr_offset(arg.data as ^byte, info.fields[i].offset)
|
||||
a.type_info = info.fields[i].type_info
|
||||
print_any_to_buffer(buf, a)
|
||||
data := arg.data as ^byte + info.fields[i].offset
|
||||
ti := info.fields[i].type_info
|
||||
print_any_to_buffer(buf, make_any(ti, data))
|
||||
}
|
||||
|
||||
case Union:
|
||||
@@ -526,8 +484,6 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
||||
print_type_to_buffer(buf, arg.type_info)
|
||||
print_string_to_buffer(buf, " @ 0x")
|
||||
print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+129
-5
@@ -93,18 +93,18 @@ AllocationHeader :: struct {
|
||||
}
|
||||
allocation_header_fill :: proc(header: ^AllocationHeader, data: rawptr, size: int) {
|
||||
header.size = size
|
||||
ptr := ptr_offset(header, 1) as ^int
|
||||
ptr := (header+1) as ^int
|
||||
|
||||
for i := 0; ptr as rawptr < data; i++ {
|
||||
ptr_offset(ptr, i)^ = -1
|
||||
(ptr+i)^ = -1
|
||||
}
|
||||
}
|
||||
allocation_header :: proc(data: rawptr) -> ^AllocationHeader {
|
||||
p := data as ^int
|
||||
for ptr_offset(p, -1)^ == -1 {
|
||||
p = ptr_offset(p, -1)
|
||||
for (p-1)^ == -1 {
|
||||
p = (p-1)
|
||||
}
|
||||
return ptr_offset(p as ^AllocationHeader, -1)
|
||||
return (p as ^AllocationHeader)-1
|
||||
}
|
||||
|
||||
|
||||
@@ -207,3 +207,127 @@ end_temp_arena_memory :: proc(using tmp: Temp_Arena_Memory) {
|
||||
arena.memory.count = original_count
|
||||
arena.temp_count--
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
align_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||
WORD_SIZE :: size_of(int)
|
||||
using Type_Info
|
||||
|
||||
match type info : type_info {
|
||||
case Named:
|
||||
return align_of_type_info(info.base)
|
||||
case Integer:
|
||||
return info.size
|
||||
case Float:
|
||||
return info.size
|
||||
case String:
|
||||
return WORD_SIZE
|
||||
case Boolean:
|
||||
return 1
|
||||
case Pointer:
|
||||
return WORD_SIZE
|
||||
case Maybe:
|
||||
return align_of_type_info(info.elem)
|
||||
case Procedure:
|
||||
return WORD_SIZE
|
||||
case Array:
|
||||
return align_of_type_info(info.elem)
|
||||
case Slice:
|
||||
return WORD_SIZE
|
||||
case Vector:
|
||||
return align_of_type_info(info.elem)
|
||||
case Struct:
|
||||
return info.align
|
||||
case Union:
|
||||
return info.align
|
||||
case Raw_Union:
|
||||
return info.align
|
||||
case Enum:
|
||||
return align_of_type_info(info.base)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
align_formula :: proc(size, align: int) -> int {
|
||||
result := size + align-1
|
||||
return result - result%align
|
||||
}
|
||||
|
||||
size_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||
WORD_SIZE :: size_of(int)
|
||||
using Type_Info
|
||||
|
||||
match type info : type_info {
|
||||
case Named:
|
||||
return size_of_type_info(info.base)
|
||||
case Integer:
|
||||
return info.size
|
||||
case Float:
|
||||
return info.size
|
||||
case Any:
|
||||
return 2*WORD_SIZE
|
||||
case String:
|
||||
return 2*WORD_SIZE
|
||||
case Boolean:
|
||||
return 1
|
||||
case Pointer:
|
||||
return WORD_SIZE
|
||||
case Maybe:
|
||||
return size_of_type_info(info.elem) + 1
|
||||
case Procedure:
|
||||
return WORD_SIZE
|
||||
case Array:
|
||||
count := info.count
|
||||
if count == 0 {
|
||||
return 0
|
||||
}
|
||||
size := size_of_type_info(info.elem)
|
||||
align := align_of_type_info(info.elem)
|
||||
alignment := align_formula(size, align)
|
||||
return alignment*(count-1) + size
|
||||
case Slice:
|
||||
return 3*WORD_SIZE
|
||||
case Vector:
|
||||
is_bool :: proc(type_info: ^Type_Info) -> bool {
|
||||
match type info : type_info {
|
||||
case Named:
|
||||
return is_bool(info.base)
|
||||
case Boolean:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
count := info.count
|
||||
if count == 0 {
|
||||
return 0
|
||||
}
|
||||
bit_size := 8*size_of_type_info(info.elem)
|
||||
if is_bool(info.elem) {
|
||||
// NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
|
||||
// Silly LLVM spec
|
||||
bit_size = 1
|
||||
}
|
||||
total_size_in_bits := bit_size * count
|
||||
total_size := (total_size_in_bits+7)/8
|
||||
return total_size
|
||||
|
||||
case Struct:
|
||||
return info.size
|
||||
case Union:
|
||||
return info.size
|
||||
case Raw_Union:
|
||||
return info.size
|
||||
case Enum:
|
||||
return size_of_type_info(info.base)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user