diff --git a/code/demo.odin b/code/demo.odin index 9fea042ff..5da0ee6bb 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,14 +1,19 @@ -#import "punity.odin" as pn +#import "punity.odin" as pn +#import "test.odin" as t1 +#import "sub/test.odin" as t2 main :: proc() { - init :: proc(c: ^pn.Core) { - } + t1.thing() + t2.thing() - step :: proc(c: ^pn.Core) { - if pn.key_down(pn.Key.ESCAPE) { - c.running = false - } - } + // init :: proc(c: ^pn.Core) { + // } - pn.run(init, step) + // step :: proc(c: ^pn.Core) { + // if pn.key_down(pn.Key.ESCAPE) { + // c.running = false + // } + // } + + // pn.run(init, step) } diff --git a/code/math.odin b/code/math.odin index d7539bcb4..5fea41adc 100644 --- a/code/math.odin +++ b/code/math.odin @@ -43,13 +43,25 @@ Mat3 :: type {9}f32 Mat4 :: type {16}f32 -fsqrt :: proc(x: f32) -> f32 #foreign "llvm.sqrt.f32" -fsin :: proc(x: f32) -> f32 #foreign "llvm.sin.f32" -fcos :: proc(x: f32) -> f32 #foreign "llvm.cos.f32" -flerp :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t } -fclamp :: proc(x, lower, upper: f32) -> f32 { return min(max(x, lower), upper) } -fclamp01 :: proc(x: f32) -> f32 { return fclamp(x, 0, 1) } -fsign :: proc(x: f32) -> f32 { if x >= 0 { return +1 } return -1 } +sqrt32 :: proc(x: f32) -> f32 #foreign "llvm.sqrt.f32" +sqrt64 :: proc(x: f64) -> f64 #foreign "llvm.sqrt.f64" + +sin32 :: proc(x: f32) -> f32 #foreign "llvm.sin.f32" +sin64 :: proc(x: f64) -> f64 #foreign "llvm.sin.f64" + +cos64 :: proc(x: f64) -> f64 #foreign "llvm.cos.f64" +cos32 :: proc(x: f32) -> f32 #foreign "llvm.cos.f32" + +lerp32 :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t } +lerp64 :: proc(a, b, t: f64) -> f64 { return a*(1-t) + b*t } + +clamp32 :: proc(x, lower, upper: f32) -> f32 { return min(max(x, lower), upper) } +clamp64 :: proc(x, lower, upper: f64) -> f64 { return min(max(x, lower), upper) } + +sign32 :: proc(x: f32) -> f32 { if x >= 0 { return +1 } return -1 } +sign64 :: proc(x: f64) -> f64 { if x >= 0 { return +1 } return -1 } + + copy_sign :: proc(x, y: f32) -> f32 { ix := x transmute u32 @@ -58,8 +70,6 @@ copy_sign :: proc(x, y: f32) -> f32 { ix |= iy & 0x80000000 return ix transmute f32 } - - round :: proc(x: f32) -> f32 { if x >= 0 { return floor(x + 0.5) @@ -79,9 +89,6 @@ ceil :: proc(x: f32) -> f32 { return ((x as int)+1) as f32 } - - - remainder :: proc(x, y: f32) -> f32 { return x - round(x/y) * y } diff --git a/code/old_runtime.odin b/code/old_runtime.odin deleted file mode 100644 index af788f11d..000000000 --- a/code/old_runtime.odin +++ /dev/null @@ -1,412 +0,0 @@ -#load "win32.odin" - -assume :: proc(cond: bool) #foreign "llvm.assume" - -__debug_trap :: proc() #foreign "llvm.debugtrap" -__trap :: proc() #foreign "llvm.trap" -read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter" - -bit_reverse16 :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16" -bit_reverse32 :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32" -bit_reverse64 :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64" - -byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16" -byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32" -byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64" - -fmuladd_f32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32" -fmuladd_f64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64" - -// TODO(bill): make custom heap procedures -heap_alloc :: proc(len: int) -> rawptr #foreign "malloc" -heap_dealloc :: proc(ptr: rawptr) #foreign "free" - -memory_zero :: proc(data: rawptr, len: int) { - d := slice_ptr(data as ^byte, len) - for i := 0; i < len; i++ { - d[i] = 0 - } -} - -memory_compare :: proc(dst, src: rawptr, len: int) -> int { - s1, s2: ^byte = dst, src - for i := 0; i < len; i++ { - a := ptr_offset(s1, i)^ - b := ptr_offset(s2, i)^ - if a != b { - return (a - b) as int - } - } - return 0 -} - -memory_copy :: proc(dst, src: rawptr, n: int) #inline { - if dst == src { - return - } - - v128b :: type {4}u32 - compile_assert(align_of(v128b) == 16) - - d, s: ^byte = dst, src - - for ; s as uint % 16 != 0 && n != 0; n-- { - d^ = s^ - d, s = ptr_offset(d, 1), ptr_offset(s, 1) - } - - if d as uint % 16 == 0 { - for ; n >= 16; d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 { - (d as ^v128b)^ = (s as ^v128b)^ - } - - if n&8 != 0 { - (d as ^u64)^ = (s as ^u64)^ - d, s = ptr_offset(d, 8), ptr_offset(s, 8) - } - if n&4 != 0 { - (d as ^u32)^ = (s as ^u32)^; - d, s = ptr_offset(d, 4), ptr_offset(s, 4) - } - if n&2 != 0 { - (d as ^u16)^ = (s as ^u16)^ - d, s = ptr_offset(d, 2), ptr_offset(s, 2) - } - if n&1 != 0 { - d^ = s^ - d, s = ptr_offset(d, 1), ptr_offset(s, 1) - } - return; - } - - // IMPORTANT NOTE(bill): Little endian only - LS :: proc(a, b: u32) -> u32 #inline { return a << b } - RS :: proc(a, b: u32) -> u32 #inline { return a >> b } - /* NOTE(bill): Big endian version - LS :: proc(a, b: u32) -> u32 #inline { return a >> b; } - RS :: proc(a, b: u32) -> u32 #inline { return a << b; } - */ - - w, x: u32 - - if d as uint % 4 == 1 { - w = (s as ^u32)^ - d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) - d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) - d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) - n -= 3 - - for n > 16 { - d32 := d as ^u32 - s32 := ptr_offset(s, 1) as ^u32 - x = s32^; d32^ = LS(w, 24) | RS(x, 8) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - w = s32^; d32^ = LS(x, 24) | RS(w, 8) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - x = s32^; d32^ = LS(w, 24) | RS(x, 8) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - w = s32^; d32^ = LS(x, 24) | RS(w, 8) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - - d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 - } - - } else if d as uint % 4 == 2 { - w = (s as ^u32)^ - d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) - d^ = s^; d = ptr_offset(d, 1); s = ptr_offset(s, 1) - n -= 2 - - for n > 17 { - d32 := d as ^u32 - s32 := ptr_offset(s, 2) as ^u32 - x = s32^; d32^ = LS(w, 16) | RS(x, 16) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - w = s32^; d32^ = LS(x, 16) | RS(w, 16) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - x = s32^; d32^ = LS(w, 16) | RS(x, 16) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - w = s32^; d32^ = LS(x, 16) | RS(w, 16) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - - d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 - } - - } else if d as uint % 4 == 3 { - w = (s as ^u32)^ - d^ = s^ - n -= 1 - - for n > 18 { - d32 := d as ^u32 - s32 := ptr_offset(s, 3) as ^u32 - x = s32^; d32^ = LS(w, 8) | RS(x, 24) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - w = s32^; d32^ = LS(x, 8) | RS(w, 24) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - x = s32^; d32^ = LS(w, 8) | RS(x, 24) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - w = s32^; d32^ = LS(x, 8) | RS(w, 24) - d32, s32 = ptr_offset(d32, 1), ptr_offset(s32, 1) - - d, s, n = ptr_offset(d, 16), ptr_offset(s, 16), n-16 - } - } - - if n&16 != 0 { - (d as ^v128b)^ = (s as ^v128b)^ - d, s = ptr_offset(d, 16), ptr_offset(s, 16) - } - if n&8 != 0 { - (d as ^u64)^ = (s as ^u64)^ - d, s = ptr_offset(d, 8), ptr_offset(s, 8) - } - if n&4 != 0 { - (d as ^u32)^ = (s as ^u32)^; - d, s = ptr_offset(d, 4), ptr_offset(s, 4) - } - if n&2 != 0 { - (d as ^u16)^ = (s as ^u16)^ - d, s = ptr_offset(d, 2), ptr_offset(s, 2) - } - if n&1 != 0 { - d^ = s^ - } -} - -memory_move :: proc(dst, src: rawptr, n: int) #inline { - d, s: ^byte = dst, src - if d == s { - return - } - if d >= ptr_offset(s, n) || ptr_offset(d, n) <= s { - memory_copy(d, s, n) - return - } - - // TODO(bill): Vectorize the shit out of this - if d < s { - if s as int % size_of(int) == d as int % size_of(int) { - for d as int % size_of(int) != 0 { - if n == 0 { - return - } - n-- - d^ = s^ - d, s = ptr_offset(d, 1), ptr_offset(s, 1) - } - di, si := d as ^int, s as ^int - for n >= size_of(int) { - di^ = si^ - di, si = ptr_offset(di, 1), ptr_offset(si, 1) - n -= size_of(int) - } - } - for ; n > 0; n-- { - d^ = s^ - d, s = ptr_offset(d, 1), ptr_offset(s, 1) - } - } else { - if s as int % size_of(int) == d as int % size_of(int) { - for ptr_offset(d, n) as int % size_of(int) != 0 { - if n == 0 { - return - } - n-- - d^ = s^ - d, s = ptr_offset(d, 1), ptr_offset(s, 1) - } - for n >= size_of(int) { - n -= size_of(int) - di := ptr_offset(d, n) as ^int - si := ptr_offset(s, n) as ^int - di^ = si^ - } - for ; n > 0; n-- { - d^ = s^ - d, s = ptr_offset(d, 1), ptr_offset(s, 1) - } - } - for n > 0 { - n-- - dn := ptr_offset(d, n) - sn := ptr_offset(s, n) - dn^ = sn^ - } - } -} - -__string_eq :: proc(a, b: string) -> bool { - if len(a) != len(b) { - return false - } - if ^a[0] == ^b[0] { - return true - } - return memory_compare(^a[0], ^b[0], len(a)) == 0 -} - -__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_ne :: proc(a, b : string) -> bool #inline { return !__string_eq(a, b) } -__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 } -__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 } -__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 } -__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 } - - - - -Allocation_Mode :: type enum { - ALLOC, - DEALLOC, - DEALLOC_ALL, - RESIZE, -} - - - -Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocation_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64) -> rawptr - -Allocator :: type struct { - procedure: Allocator_Proc; - data: rawptr -} - - -Context :: type struct { - thread_ptr: rawptr - - user_data: rawptr - user_index: int - - allocator: Allocator -} - -#thread_local context: Context - -DEFAULT_ALIGNMENT :: 2*size_of(int) - - -__check_context :: proc() { - if context.allocator.procedure == null { - context.allocator = __default_allocator() - } - if context.thread_ptr == null { - // TODO(bill): - // context.thread_ptr = current_thread_pointer() - } -} - - -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_Mode.ALLOC, size, alignment, null, 0, 0) -} - -dealloc :: proc(ptr: rawptr) #inline { - __check_context() - a := context.allocator - _ = a.procedure(a.data, Allocation_Mode.DEALLOC, 0, 0, ptr, 0, 0) -} -dealloc_all :: proc(ptr: rawptr) #inline { - __check_context() - a := context.allocator - _ = a.procedure(a.data, Allocation_Mode.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_Mode.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 { - return old_memory - } - - new_memory := alloc_align(new_size, alignment) - if new_memory == null { - return null - } - - memory_copy(new_memory, old_memory, min(old_size, new_size)); - dealloc(old_memory) - return new_memory -} - - -__default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocation_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, flags: u64) -> rawptr { - using Allocation_Mode - match mode { - case ALLOC: - return heap_alloc(size) - case RESIZE: - return default_resize_align(old_memory, old_size, size, alignment) - case DEALLOC: - heap_dealloc(old_memory) - case DEALLOC_ALL: - // NOTE(bill): Does nothing - } - - return null -} - -__default_allocator :: proc() -> Allocator { - return Allocator{ - __default_allocator_proc, - null, - } -} - - - - -__assert :: proc(msg: string) { - file_write(file_get_standard(File_Standard.ERROR), msg as []byte) - // TODO(bill): Which is better? - // __trap() - __debug_trap() -} diff --git a/code/punity.odin b/code/punity.odin index 585d0b4b5..4c0253acc 100644 --- a/code/punity.odin +++ b/code/punity.odin @@ -1,5 +1,5 @@ #import "win32.odin" as win32 -#import "fmt.odin" as _ +#import "fmt.odin" as fmt CANVAS_WIDTH :: 128 CANVAS_HEIGHT :: 128 @@ -357,7 +357,7 @@ run :: proc(user_init, user_step: proc(c: ^Core)) { } if RegisterClassExA(^window_class) == 0 { - /*fmt.*/println_err("RegisterClassExA failed") + fmt.println_err("RegisterClassExA failed") return } @@ -386,7 +386,7 @@ run :: proc(user_init, user_step: proc(c: ^Core)) { null); if win32_window == null { - /*fmt.*/println_err("CreateWindowExA failed") + fmt.println_err("CreateWindowExA failed") return } @@ -434,7 +434,7 @@ run :: proc(user_init, user_step: proc(c: ^Core)) { { data: [128]byte buf := data[:0] - /*fmt.*/print_to_buffer(^buf, "Punity: % ms\x00", dt*1000) + fmt.print_to_buffer(^buf, "Punity: % ms\x00", dt*1000) win32.SetWindowTextA(win32_window, buf.data) } diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 27c6d04b5..cc7099e96 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -354,12 +354,13 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit continue; } - if (e->scope == shared) { - // Do not return imported entities - if (entity_) *entity_ = e; - if (scope_) *scope_ = shared; - return; + if (e->scope != shared) { + // Do not return imported entities even #load ones + continue; } + if (entity_) *entity_ = e; + if (scope_) *scope_ = shared; + return; } } } @@ -529,13 +530,12 @@ void destroy_checker_info(CheckerInfo *i) { } -void init_checker(Checker *c, Parser *parser) { +void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) { gbAllocator a = gb_heap_allocator(); c->parser = parser; init_checker_info(&c->info); - c->sizes.word_size = 8; - c->sizes.max_align = 8; + c->sizes = sizes; gb_array_init(c->proc_stack, a); gb_array_init(c->procs, a); @@ -832,6 +832,7 @@ void check_type_name_cycles(Checker *c, CycleCheck *cc, Entity *e) { // if (t->kind == Type_Named) { // if (t->Named.type_name == e) { // gb_printf("Illegal cycle %.*s!!!\n", LIT(e->token.string)); + // GB_PANIC("!!!"); // } // } } @@ -841,9 +842,8 @@ void init_type_info_types(Checker *c) { String type_info_str = make_string("Type_Info"); Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str); if (e == NULL) { - gb_printf_err("Internal Compiler Error: Could not find type declaration for `Type_Info`\n"); - gb_printf_err("Is `runtime.odin` missing from the `core` directory?\n"); - gb_exit(1); + compiler_error("Could not find type declaration for `Type_Info`\n" + "Is `runtime.odin` missing from the `core` directory relative to odin.exe?"); } t_type_info = e->type; t_type_info_ptr = make_type_pointer(c->allocator, t_type_info); @@ -854,8 +854,7 @@ void init_type_info_types(Checker *c) { t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member); if (record->field_count != 16) { - gb_printf_err("Internal Compiler Error: Invalid `Type_Info` layout\n"); - gb_exit(1); + compiler_error("Invalid `Type_Info` layout"); } t_type_info_named = record->fields[ 1]->type; t_type_info_integer = record->fields[ 2]->type; @@ -1042,6 +1041,8 @@ void check_parsed_files(Checker *c) { } if (!previously_added) { gb_array_append(file_scope->imported, scope); + } else { + warning(id->token, "Multiple #import of the same file within this scope"); } if (are_strings_equal(id->import_name.string, make_string("_"))) { diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp index fd9c5ce8a..dea0e2e0f 100644 --- a/src/checker/entity.cpp +++ b/src/checker/entity.cpp @@ -26,37 +26,37 @@ String const entity_strings[] = { }; -typedef i64 EntityGuid; typedef struct Type Type; struct Entity { EntityKind kind; - EntityGuid guid; - Scope *scope; - Token token; - Type *type; - Entity *using_parent; - AstNode *using_expr; + Scope * scope; + Token token; + Type * type; + Entity * using_parent; + AstNode * using_expr; union { - struct { ExactValue value; } Constant; struct { - b8 visited; // Cycle detection - b8 used; // Variable is used - b8 anonymous; // Variable is an anonymous - b8 is_using; // `using` variable + ExactValue value; + } Constant; + struct { + b8 visited; // Cycle detection + b8 used; // Variable is used + b8 anonymous; // Variable is an anonymous + b8 is_using; // `using` variable i32 field_index; // Order in source b8 is_field; // Is struct field } Variable; struct { - // struct DeclInfo *decl; // Usually NULL } TypeName; struct { - b8 pure; } Procedure; - struct { BuiltinProcId id; } Builtin; + struct { + BuiltinProcId id; + } Builtin; struct { String path; String name; @@ -78,16 +78,10 @@ b32 is_entity_exported(Entity *e) { return true; } -gb_global gbAtomic64 entity_guid_counter = {0}; - -EntityGuid next_entity_guid(void) { - return cast(EntityGuid)gb_atomic64_fetch_add(&entity_guid_counter, 1); -} Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) { Entity *entity = gb_alloc_item(a, Entity); entity->kind = kind; - entity->guid = next_entity_guid(); entity->scope = scope; entity->token = token; entity->type = type; diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index fa6f2ae0b..a8e590728 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -668,7 +668,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc -void check_var_decl(Checker *c, AstNode *node) { +void check_var_decl_node(Checker *c, AstNode *node) { ast_node(vd, VarDecl, node); isize entity_count = gb_array_count(vd->names); isize entity_index = 0; @@ -736,7 +736,7 @@ void check_var_decl(Checker *c, AstNode *node) { } -void check_const_decl(Checker *c, AstNode *node) { +void check_const_decl_node(Checker *c, AstNode *node) { ast_node(vd, ConstDecl, node); isize entity_count = gb_array_count(vd->names); isize entity_index = 0; @@ -1425,7 +1425,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { if (gb_array_count(vd->names) > 1 && vd->type != NULL) { error(us->token, "`using` can only be applied to one variable of the same type"); } - check_var_decl(c, us->node); + check_var_decl_node(c, us->node); gb_for_array(name_index, vd->names) { AstNode *item = vd->names[name_index]; @@ -1467,11 +1467,11 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { case_ast_node(vd, VarDecl, node); - check_var_decl(c, node); + check_var_decl_node(c, node); case_end; case_ast_node(cd, ConstDecl, node); - check_const_decl(c, node); + check_const_decl_node(c, node); case_end; case_ast_node(pd, ProcDecl, node); diff --git a/src/checker/type.cpp b/src/checker/type.cpp index 2c2e650c8..96b0149f7 100644 --- a/src/checker/type.cpp +++ b/src/checker/type.cpp @@ -96,7 +96,7 @@ enum TypeRecordKind { }; struct Type { - u32 flags; + u32 flags; // See parser.cpp `enum TypeFlag` TypeKind kind; union { BasicType Basic; @@ -908,9 +908,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { case Type_Vector: { i64 size = type_size_of(s, allocator, t->Vector.elem); size *= t->Vector.count; - size = next_pow2(size); + size = prev_pow2(size); // TODO(bill): Type_Vector type_align_of - return gb_clamp(size, s.max_align, 4*s.max_align); + return gb_clamp(size, 1, s.max_align); } break; case Type_Record: { @@ -920,8 +920,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { i64 max = 1; for (isize i = 0; i < t->Record.field_count; i++) { i64 align = type_align_of(s, allocator, t->Record.fields[i]->type); - if (max < align) + if (max < align) { max = align; + } } return max; } @@ -931,8 +932,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { for (isize i = 1; i < t->Record.field_count; i++) { // NOTE(bill): field zero is null i64 align = type_align_of(s, allocator, t->Record.fields[i]->type); - if (max < align) + if (max < align) { max = align; + } } return max; } break; @@ -940,8 +942,9 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { i64 max = 1; for (isize i = 0; i < t->Record.field_count; i++) { i64 align = type_align_of(s, allocator, t->Record.fields[i]->type); - if (max < align) + if (max < align) { max = align; + } } return max; } break; @@ -955,7 +958,6 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { } i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, b32 is_packed) { - // TODO(bill): use arena allocation i64 *offsets = gb_alloc_array(allocator, i64, field_count); i64 curr_offset = 0; if (is_packed) { @@ -1040,8 +1042,9 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { switch (t->Record.kind) { case TypeRecord_Struct: { i64 count = t->Record.field_count; - if (count == 0) + if (count == 0) { return 0; + } type_set_offsets(s, allocator, t); return t->Record.struct_offsets[count-1] + type_size_of(s, allocator, t->Record.fields[count-1]->type); } break; diff --git a/src/codegen/codegen.cpp b/src/codegen/codegen.cpp index a33b9e633..ad3fc54a0 100644 --- a/src/codegen/codegen.cpp +++ b/src/codegen/codegen.cpp @@ -31,6 +31,40 @@ void ssa_gen_destroy(ssaGen *s) { gb_file_close(&s->output_file); } +String ssa_mangle_name(ssaGen *s, String path, String name) { + // NOTE(bill): prefix names not in the init scope + // TODO(bill): make robust and not just rely on the file's name + + ssaModule *m = &s->module; + CheckerInfo *info = m->info; + gbAllocator a = m->allocator; + AstFile *file = *map_get(&info->files, hash_string(path)); + + char *str = gb_alloc_array(a, char, path.len+1); + gb_memcopy(str, path.text, path.len); + str[path.len] = 0; + for (isize i = 0; i < path.len; i++) { + if (str[i] == '\\') { + str[i] = '/'; + } + + } + + char const *base = gb_path_base_name(str); + char const *ext = gb_path_extension(base); + isize base_len = ext-1-base; + + isize max_len = base_len + 1 + 10 + 1 + name.len; + u8 *new_name = gb_alloc_array(a, u8, max_len); + isize new_name_len = gb_snprintf( + cast(char *)new_name, max_len, + "%.*s$%u.%.*s", + base_len, base, + file->id, + LIT(name)); + + return make_string(new_name, new_name_len-1); +} void ssa_gen_tree(ssaGen *s) { if (v_zero == NULL) { @@ -62,34 +96,8 @@ void ssa_gen_tree(ssaGen *s) { DeclInfo *decl = entry->value; Scope *scope = e->scope; - if (scope->is_global || - scope->is_init) { - - } else { - // NOTE(bill): prefix names not in the init scope - // TODO(bill): make robust and not just rely on the file's name - String path = e->token.pos.file; - char *str = gb_alloc_array(a, char, path.len+1); - gb_memcopy(str, path.text, path.len); - str[path.len] = 0; - for (isize i = 0; i < path.len; i++) { - if (str[i] == '\\') { - str[i] = '/'; - } - - } - char const *base = gb_path_base_name(str); - char const *ext = gb_path_extension(base); - isize base_len = ext-1-base; - - isize new_len = base_len + 1 + name.len; - u8 *new_name = gb_alloc_array(a, u8, new_len); - gb_memcopy(new_name, base, base_len); - new_name[base_len] = '.'; - gb_memcopy(new_name+base_len+1, name.text, name.len); - - name = make_string(new_name, new_len); - // gb_printf("%.*s\n", new_len, new_name); + if (!scope->is_global && !scope->is_init) { + name = ssa_mangle_name(s, e->token.pos.file, name); } diff --git a/src/codegen/print_llvm.cpp b/src/codegen/print_llvm.cpp index a621af244..ef38a45fb 100644 --- a/src/codegen/print_llvm.cpp +++ b/src/codegen/print_llvm.cpp @@ -119,7 +119,7 @@ void ssa_print_encoded_local(ssaFileBuffer *f, String name) { ssa_print_escape_string(f, name, true); } -void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope = false) { +void ssa_print_encoded_global(ssaFileBuffer *f, String name, b32 global_scope) { ssa_fprintf(f, "@"); if (!global_scope && !are_strings_equal(name, make_string("main"))) { ssa_fprintf(f, "."); @@ -337,20 +337,25 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type ssa_print_encoded_local(f, value->TypeName.name); break; case ssaValue_Global: { + Scope *scope = value->Global.entity->scope; + b32 in_global_scope = false; + if (scope != NULL) { + in_global_scope = scope->is_global || scope->is_init; + } if (type_hint != NULL && is_type_string(type_hint)) { ssa_fprintf(f, "{i8* getelementptr inbounds ("); ssa_print_type(f, m->sizes, value->Global.entity->type); ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, value->Global.entity->type); ssa_fprintf(f, "* "); - ssa_print_encoded_global(f, value->Global.entity->token.string); + ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope); ssa_fprintf(f, ", "); ssa_print_type(f, m->sizes, t_int); ssa_fprintf(f, " 0, i32 0), "); ssa_print_type(f, m->sizes, t_int); ssa_fprintf(f, " %lld}", 0); } else { - ssa_print_encoded_global(f, value->Global.entity->token.string); + ssa_print_encoded_global(f, value->Global.entity->token.string, in_global_scope); } } break; case ssaValue_Param: @@ -374,7 +379,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) { switch (instr->kind) { case ssaInstr_StartupRuntime: { ssa_fprintf(f, "call void "); - ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME)); + ssa_print_encoded_global(f, make_string(SSA_STARTUP_RUNTIME_PROC_NAME), false); ssa_fprintf(f, "()\n"); } break; @@ -823,10 +828,6 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) { } - if (proc->tags & ProcTag_foreign) { - ssa_fprintf(f, "; foreign\n"); - } - if (proc->body != NULL) { // ssa_fprintf(f, "nounwind uwtable {\n"); @@ -915,7 +916,12 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) { continue; } auto *g = &v->Global; - ssa_print_encoded_global(f, g->entity->token.string); + Scope *scope = g->entity->scope; + b32 in_global_scope = false; + if (scope != NULL) { + in_global_scope = scope->is_global || scope->is_init; + } + ssa_print_encoded_global(f, g->entity->token.string, in_global_scope); ssa_fprintf(f, " = "); if (g->is_thread_local) { ssa_fprintf(f, "thread_local "); diff --git a/src/common.cpp b/src/common.cpp index 890c82373..db0a6ebdb 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -4,6 +4,21 @@ #include "string.cpp" + +struct BlockTimer { + u64 start; + u64 finish; + char *msg; + BlockTimer(char *msg) : msg(msg) { + start = gb_utc_time_now(); + } + ~BlockTimer() { + finish = gb_utc_time_now(); + gb_printf_err("%s - %llu us\n", finish-start); + } +}; + + // Hasing struct HashKey { @@ -45,6 +60,9 @@ b32 hash_key_equal(HashKey a, HashKey b) { } i64 next_pow2(i64 n) { + if (n <= 0) { + return 0; + } n--; n |= n >> 1; n |= n >> 2; @@ -56,6 +74,19 @@ i64 next_pow2(i64 n) { return n; } +i64 prev_pow2(i64 n) { + if (n <= 0) { + return 0; + } + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + n |= n >> 32; + return n - (n >> 1); +} + #define gb_for_array(index_, array_) for (isize index_ = 0; (array_) != NULL && index_ < gb_array_count(array_); index_++) diff --git a/src/main.cpp b/src/main.cpp index 2191aaa5d..cfbc6ba17 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,20 +40,19 @@ i32 win32_exec_command_line_app(char *fmt, ...) { } } - #if defined(DISPLAY_TIMING) -#define INIT_TIMER() u64 start_time, end_time = 0, total_time = 0; start_time = gb_utc_time_now() +#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0 #define PRINT_TIMER(section) do { \ - u64 diff; \ - end_time = gb_utc_time_now(); \ + f64 diff; \ + end_time = gb_time_now(); \ diff = end_time - start_time; \ total_time += diff; \ - gb_printf_err("%s: %.1f ms\n", section, diff/1000.0f); \ - start_time = gb_utc_time_now(); \ + gb_printf_err("%s: %.1f ms\n", section, diff*1000.0); \ + start_time = gb_time_now(); \ } while (0) #define PRINT_ACCUMULATION() do { \ - gb_printf_err("Total compilation time: %lld ms\n", total_time/1000); \ + gb_printf_err("Total compilation time: %.1f ms\n", total_time*1000.0); \ } while (0) #else #define INIT_TIMER() @@ -94,8 +93,12 @@ int main(int argc, char **argv) { #if 1 Checker checker = {}; + BaseTypeSizes sizes = {}; + // NOTE(bill): x64 + sizes.word_size = 8; + sizes.max_align = 16; - init_checker(&checker, &parser); + init_checker(&checker, &parser, sizes); defer (destroy_checker(&checker)); check_parsed_files(&checker); diff --git a/src/parser.cpp b/src/parser.cpp index 08383fa94..ed967ad97 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -17,6 +17,7 @@ enum ParseFileError { typedef gbArray(AstNode *) AstNodeArray; struct AstFile { + u32 id; gbArena arena; Tokenizer tokenizer; gbArray(Token) tokens; @@ -2661,12 +2662,14 @@ ParseFileError init_ast_file(AstFile *f, String fullpath) { gb_array_init(f->tokens, gb_heap_allocator()); for (;;) { Token token = tokenizer_get_token(&f->tokenizer); - if (token.kind == Token_Invalid) + if (token.kind == Token_Invalid) { return ParseFile_InvalidToken; + } gb_array_append(f->tokens, token); - if (token.kind == Token_EOF) + if (token.kind == Token_EOF) { break; + } } f->cursor = &f->tokens[0]; @@ -2842,6 +2845,7 @@ void parse_file(Parser *p, AstFile *f) { } base_dir.len--; } + gbAllocator allocator = gb_heap_allocator(); // TODO(bill): Change this allocator f->decls = parse_stmt_list(f); @@ -2917,26 +2921,11 @@ ParseFileError parse_files(Parser *p, char *init_filename) { AstFile file = {}; ParseFileError err = init_ast_file(&file, import_path); - // if (err == ParseFile_NotFound) { - // // HACK(bill): Check core directory - // char buf[300] = {}; - // char core[] = "W:/Odin/core/"; - // isize len = gb_size_of(core)-1; - // gb_memcopy(buf, core, len); - // gb_memcopy(buf+len, import_rel_path.text, import_rel_path.len); - // char *path = gb_path_get_full_name(gb_heap_allocator(), buf); - // gb_printf_err("%s\n", path); - - // import_path = make_string(path); - // err = init_ast_file(&file, import_path); - // p->imports[i].path = import_path; - // } - if (err != ParseFile_None) { if (pos.line != 0) { gb_printf_err("%.*s(%td:%td) ", LIT(pos.file), pos.line, pos.column); } - gb_printf_err("Failed to parse file: %.*s\n", LIT(import_path)); + gb_printf_err("Failed to parse file: %.*s\n", LIT(import_rel_path)); switch (err) { case ParseFile_WrongExtension: gb_printf_err("\tInvalid file extension\n"); @@ -2960,6 +2949,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) { return err; } parse_file(p, &file); + file.id = gb_array_count(p->files); gb_array_append(p->files, file); p->total_token_count += gb_array_count(file.tokens); } diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 6f645b7a6..6c3604406 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -210,6 +210,17 @@ void syntax_error(Token token, char *fmt, ...) { } +void compiler_error(char *fmt, ...) { + va_list va; + + va_start(va, fmt); + gb_printf_err("Internal Compiler Error: %s\n", + gb_bprintf_va(fmt, va)); + va_end(va); + gb_exit(1); +} + + // NOTE(bill): result == priority i32 token_precedence(Token t) { @@ -354,6 +365,7 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) { defer (gb_free(gb_heap_allocator(), c_str)); + gbFileContents fc = gb_file_read_contents(gb_heap_allocator(), true, c_str); gb_zero_item(t); if (fc.data != NULL) {