Add Pointer Arithmetic

This commit is contained in:
Ginger Bill
2016-10-12 17:51:36 +01:00
parent f5318c46d1
commit f3209584a3
12 changed files with 414 additions and 173 deletions
+10 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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
}