diff --git a/core/_preload.odin b/core/_preload.odin index 4bac34ed8..7d1a111ff 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -29,8 +29,8 @@ Type_Info_Record :: struct #ordered { types: []^Type_Info, names: []string, offsets: []int, // offsets may not be used in tuples - size: int, // in bytes - align: int, // in bytes + // size: int, + // align: int, packed: bool, ordered: bool, custom_align: bool, @@ -39,7 +39,6 @@ Type_Info_Record :: struct #ordered { Type_Info :: union { size: int, align: int, - Named{name: string, base: ^Type_Info}, Integer{signed: bool}, Float{}, @@ -95,6 +94,9 @@ Type_Info :: union { // This will be set by the compiler __type_table: []Type_Info; +__argv__: ^^byte; +__argc__: i32; + type_info_base :: proc(info: ^Type_Info) -> ^Type_Info { if info == nil { return nil; @@ -422,7 +424,6 @@ __abs_quaternion256 :: proc(x: quaternion256) -> f64 #inline { - __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, cap: int) { array := cast(^raw.Dynamic_Array)array_; __check_context(); diff --git a/core/fmt.odin b/core/fmt.odin index f1b6413d2..fa7d3893f 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -107,19 +107,19 @@ write_type :: proc(buf: ^[]byte, ti: ^Type_Info) { } case Float: - match 8*info.size { - case 32: write_string(buf, "f32"); - case 64: write_string(buf, "f64"); + match info.size { + case 4: write_string(buf, "f32"); + case 8: write_string(buf, "f64"); } case Complex: - match 8*info.size { - case 64: write_string(buf, "complex64"); - case 128: write_string(buf, "complex128"); + match info.size { + case 8: write_string(buf, "complex64"); + case 16: write_string(buf, "complex128"); } case Quaternion: - match 8*info.size { - case 128: write_string(buf, "quaternion128"); - case 256: write_string(buf, "quaternion256"); + match info.size { + case 16: write_string(buf, "quaternion128"); + case 32: write_string(buf, "quaternion"); } case String: write_string(buf, "string"); case Boolean: write_string(buf, "bool"); @@ -389,7 +389,6 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) { arg.type_info = type_info_base(arg.type_info); match i in arg { case int: num = i; - case uint: num = cast(int)i; case i8: num = cast(int)i; case i16: num = cast(int)i; case i32: num = cast(int)i; diff --git a/core/opengl.odin b/core/opengl.odin index 88ea8c4b4..d5c322a17 100644 --- a/core/opengl.odin +++ b/core/opengl.odin @@ -1,4 +1,5 @@ #foreign_system_library lib "opengl32.lib" when ODIN_OS == "windows"; +#foreign_system_library lib "gl" when ODIN_OS == "linux"; #import win32 "sys/windows.odin" when ODIN_OS == "windows"; #import "sys/wgl.odin" when ODIN_OS == "windows"; #load "opengl_constants.odin"; diff --git a/core/os_linux.odin b/core/os_linux.odin index 731361594..b439b3dc4 100644 --- a/core/os_linux.odin +++ b/core/os_linux.odin @@ -3,10 +3,7 @@ Handle :: i32; File_Time :: u64; -Errno :: int; - -// TODO(zangent): Find out how to make this work on x64 and x32. -AddressSize :: i64; +Errno :: i32; // INVALID_HANDLE: Handle : -1; @@ -36,12 +33,13 @@ RTLD_NOW :: 0x002; RTLD_BINDING_MASK :: 0x3; RTLD_GLOBAL :: 0x100; -args: [dynamic]string; +// "Argv" arguments converted to Odin strings +immutable args := _alloc_command_line_arguments(); -FileTime :: struct #ordered { - seconds: i64, +_File_Time :: struct #ordered { + seconds: i64, nanoseconds: i32, - reserved: i32 + reserved: i32, } // Translated from @@ -49,27 +47,27 @@ FileTime :: struct #ordered { // Validity is not guaranteed. Stat :: struct #ordered { - device_id : u64, // ID of device containing file - serial : u64, // File serial number - nlink : u32, // Number of hard links - mode : u32, // Mode of the file - uid : u32, // User ID of the file's owner - gid : u32, // Group ID of the file's group - _padding : i32, // 32 bits of padding - rdev : u64, // Device ID, if device - size : i64, // Size of the file, in bytes - block_size : i64, // Optimal bllocksize for I/O - blocks : i64, // Number of 512-byte blocks allocated + device_id: u64, // ID of device containing file + serial: u64, // File serial number + nlink: u32, // Number of hard links + mode: u32, // Mode of the file + uid: u32, // User ID of the file's owner + gid: u32, // Group ID of the file's group + _padding: i32, // 32 bits of padding + rdev: u64, // Device ID, if device + size: i64, // Size of the file, in bytes + block_size: i64, // Optimal bllocksize for I/O + blocks: i64, // Number of 512-byte blocks allocated - last_access : FileTime, // Time of last access - modified : FileTime, // Time of last modification - status_change : FileTime, // Time of last status change + last_access: _File_Time, // Time of last access + modified: _File_Time, // Time of last modification + status_change: _File_Time, // Time of last status change _reserve1, _reserve2, - _reserve3 : i64, - serial : u64, // File serial number...? Maybe. - _reserve4 : i64 + _reserve3: i64, + serial_numbe: u64, // File serial number...? Maybe. + _reserve4: i64, }; // File type @@ -125,32 +123,32 @@ F_OK :: 0; // Test for file existance #foreign_system_library dl "dl"; #foreign_system_library libc "c"; -unix_open :: proc(path: ^u8, mode: int) -> Handle #foreign libc "open"; -unix_close :: proc(handle: Handle) #foreign libc "close"; -unix_read :: proc(handle: Handle, buffer: rawptr, count: int) -> AddressSize #foreign libc "read"; -unix_write :: proc(handle: Handle, buffer: rawptr, count: int) -> AddressSize #foreign libc "write"; -unix_lseek :: proc(fs: Handle, offset: AddressSize, whence: int) -> AddressSize #foreign libc "lseek"; -unix_gettid :: proc() -> u64 #foreign libc "gettid"; -unix_stat :: proc(path: ^u8, stat: ^Stat) -> int #foreign libc "stat"; -unix_access :: proc(path: ^u8, mask: int) -> int #foreign libc "access"; +_unix_open :: proc(path: ^u8, mode: int) -> Handle #foreign libc "open"; +_unix_close :: proc(fd: Handle) -> i32 #foreign libc "close"; +_unix_read :: proc(fd: Handle, buf: rawptr, size: int) -> int #foreign libc "read"; +_unix_write :: proc(fd: Handle, buf: rawptr, size: int) -> int #foreign libc "write"; +_unix_seek :: proc(fd: Handle, offset: i64, whence: i32) -> i64 #foreign libc "lseek64"; +_unix_gettid :: proc() -> u64 #foreign libc "gettid"; +_unix_stat :: proc(path: ^u8, stat: ^Stat) -> i32 #foreign libc "stat"; +_unix_access :: proc(path: ^u8, mask: int) -> i32 #foreign libc "access"; -unix_malloc :: proc(size: int) -> rawptr #foreign libc "malloc"; -unix_free :: proc(ptr: rawptr) #foreign libc "free"; -unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr #foreign libc "realloc"; -unix_getenv :: proc(^u8) -> ^u8 #foreign libc "getenv"; +_unix_malloc :: proc(size: int) -> rawptr #foreign libc "malloc"; +_unix_free :: proc(ptr: rawptr) #foreign libc "free"; +_unix_realloc :: proc(ptr: rawptr, size: int) -> rawptr #foreign libc "realloc"; +_unix_getenv :: proc(^u8) -> ^u8 #foreign libc "getenv"; -unix_exit :: proc(status: int) #foreign libc "exit"; +_unix_exit :: proc(status: int) #foreign libc "exit"; -unix_dlopen :: proc(filename: ^u8, flags: int) -> rawptr #foreign dl "dlopen"; -unix_dlsym :: proc(handle: rawptr, symbol: ^u8) -> (proc() #cc_c) #foreign dl "dlsym"; -unix_dlclose :: proc(handle: rawptr) -> int #foreign dl "dlclose"; -unix_dlerror :: proc() -> ^u8 #foreign dl "dlerror"; +_unix_dlopen :: proc(filename: ^u8, flags: int) -> rawptr #foreign dl "dlopen"; +_unix_dlsym :: proc(handle: rawptr, symbol: ^u8) -> (proc() #cc_c) #foreign dl "dlsym"; +_unix_dlclose :: proc(handle: rawptr) -> int #foreign dl "dlclose"; +_unix_dlerror :: proc() -> ^u8 #foreign dl "dlerror"; // TODO(zangent): Change this to just `open` when Bill fixes overloading. open_simple :: proc(path: string, mode: int) -> (Handle, Errno) { cstr := strings.new_c_string(path); - handle := unix_open(cstr, mode); + handle := _unix_open(cstr, mode); free(cstr); if(handle == -1) { return 0, 1; @@ -163,44 +161,29 @@ open :: proc(path: string, mode: int, perm: u32) -> (Handle, Errno) { } close :: proc(fd: Handle) { - unix_close(fd); + _unix_close(fd); } -write :: proc(fd: Handle, data: []byte) -> (AddressSize, Errno) { - assert(fd != -1); - - bytes_written := unix_write(fd, ^data[0], len(data)); - if(bytes_written == -1) { - return 0, 1; - } - return bytes_written, 0; +read :: proc(fd: Handle, data: []byte) -> (int, Errno) { + sz := _unix_read(fd, ^data[0], len(data)); + return sz, 0; } -read :: proc(fd: Handle, data: []byte) -> (AddressSize, Errno) { - assert(fd != -1); - - bytes_read := unix_read(fd, ^data[0], len(data)); - if(bytes_read == -1) { - return 0, 1; - } - return bytes_read, 0; +write :: proc(fd: Handle, data: []byte) -> (int, Errno) { + sz := _unix_write(fd, ^data[0], len(data)); + return sz, 0; } -seek :: proc(fd: Handle, offset: AddressSize, whence: int) -> (AddressSize, Errno) { - assert(fd != -1); - - final_offset := unix_lseek(fd, offset, whence); - if(final_offset == -1) { - return 0, 1; - } - return final_offset, 0; +seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) { + res := _unix_seek(fd, offset, cast(i32)whence); + return res, 0; } // NOTE(bill): Uses startup to initialize it -stdin: Handle = 0; // get_std_handle(win32.STD_INPUT_HANDLE); -stdout: Handle = 1; // get_std_handle(win32.STD_OUTPUT_HANDLE); -stderr: Handle = 2; // get_std_handle(win32.STD_ERROR_HANDLE); +stdin: Handle = 0; +stdout: Handle = 1; +stderr: Handle = 2; /* TODO(zangent): Implement these! last_write_time :: proc(fd: Handle) -> File_Time {} @@ -211,35 +194,36 @@ stat :: proc(path: string) -> (Stat, int) #inline { s: Stat; cstr := strings.new_c_string(path); defer free(cstr); - ret_int := unix_stat(cstr, ^s); - return s, ret_int; + ret_int := _unix_stat(cstr, ^s); + return s, cast(int)ret_int; } access :: proc(path: string, mask: int) -> bool #inline { cstr := strings.new_c_string(path); defer free(cstr); - return unix_access(cstr, mask) == 0; + return _unix_access(cstr, mask) == 0; } read_entire_file :: proc(name: string) -> ([]byte, bool) { + fd: Handle; + err: Errno; + size: i64; - handle, err := open_simple(name, O_RDONLY); + fd, err = open_simple(name, O_RDONLY); if(err != 0) { fmt.println("Failed to open file."); return nil, false; } - defer(close(handle)); + defer close(fd); - // We have a file! - - size: AddressSize; - size, err = seek(handle, 0, SEEK_END); + // We have a file + size, err = seek(fd, 0, SEEK_END); if(err != 0) { fmt.println("Failed to seek to end of file."); return nil, false; } - _, err = seek(handle, 0, SEEK_SET); + _, err = seek(fd, 0, SEEK_SET); if(err != 0) { fmt.println("Failed to seek to beginning of file."); return nil, false; @@ -253,7 +237,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) { return nil, false; } - read(handle, data); + read(fd, data); data[size] = 0; return data, true; @@ -261,20 +245,20 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) { heap_alloc :: proc(size: int) -> rawptr { assert(size > 0); - return unix_malloc(size); + return _unix_malloc(size); } heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { - return unix_realloc(ptr, new_size); + return _unix_realloc(ptr, new_size); } heap_free :: proc(ptr: rawptr) { - unix_free(ptr); + _unix_free(ptr); } getenv :: proc(name: string) -> (string, bool) { path_str := strings.new_c_string(name); - cstr: ^u8 = unix_getenv(path_str); + cstr: ^u8 = _unix_getenv(path_str); free(path_str); if(cstr == nil) { return "", false; @@ -283,31 +267,37 @@ getenv :: proc(name: string) -> (string, bool) { } exit :: proc(code: int) { - unix_exit(code); + _unix_exit(code); } current_thread_id :: proc() -> int { - // return cast(int) unix_gettid(); + // return cast(int) _unix_gettid(); return 0; } dlopen :: proc(filename: string, flags: int) -> rawptr #inline { cstr := strings.new_c_string(filename); - handle := unix_dlopen(cstr, flags); + handle := _unix_dlopen(cstr, flags); free(cstr); return handle; } dlsym :: proc(handle: rawptr, symbol: string) -> (proc() #cc_c) #inline { assert(handle != nil); cstr := strings.new_c_string(symbol); - proc_handle := unix_dlsym(handle, cstr); + proc_handle := _unix_dlsym(handle, cstr); free(cstr); return proc_handle; } dlclose :: proc(handle: rawptr) -> bool #inline { assert(handle != nil); - return unix_dlclose(handle) == 0; + return _unix_dlclose(handle) == 0; } dlerror :: proc() -> string { - return strings.to_odin_string(unix_dlerror()); + return strings.to_odin_string(_unix_dlerror()); +} + + +_alloc_command_line_arguments :: proc() -> []string { + // TODO(bill): + return nil; } diff --git a/core/sync.odin b/core/sync.odin index 72f784f6d..485df759a 100644 --- a/core/sync.odin +++ b/core/sync.odin @@ -1,91 +1,2 @@ -#import win32 "sys/windows.odin" when ODIN_OS == "windows"; -#import "atomic.odin"; - -Semaphore :: struct { - _handle: win32.Handle, -} - -Mutex :: struct { - _semaphore: Semaphore, - _counter: i32, - _owner: i32, - _recursion: i32, -} - -current_thread_id :: proc() -> i32 { - return cast(i32)win32.GetCurrentThreadId(); -} - -semaphore_init :: proc(s: ^Semaphore) { - s._handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil); -} - -semaphore_destroy :: proc(s: ^Semaphore) { - win32.CloseHandle(s._handle); -} - -semaphore_post :: proc(s: ^Semaphore, count: int) { - win32.ReleaseSemaphore(s._handle, cast(i32)count, nil); -} - -semaphore_release :: proc(s: ^Semaphore) #inline { semaphore_post(s, 1); } - -semaphore_wait :: proc(s: ^Semaphore) { - win32.WaitForSingleObject(s._handle, win32.INFINITE); -} - - -mutex_init :: proc(m: ^Mutex) { - atomic.store(^m._counter, 0); - atomic.store(^m._owner, current_thread_id()); - semaphore_init(^m._semaphore); - m._recursion = 0; -} -mutex_destroy :: proc(m: ^Mutex) { - semaphore_destroy(^m._semaphore); -} -mutex_lock :: proc(m: ^Mutex) { - thread_id := current_thread_id(); - if atomic.fetch_add(^m._counter, 1) > 0 { - if thread_id != atomic.load(^m._owner) { - semaphore_wait(^m._semaphore); - } - } - atomic.store(^m._owner, thread_id); - m._recursion++; -} -mutex_try_lock :: proc(m: ^Mutex) -> bool { - thread_id := current_thread_id(); - if atomic.load(^m._owner) == thread_id { - atomic.fetch_add(^m._counter, 1); - } else { - expected: i32 = 0; - if atomic.load(^m._counter) != 0 { - return false; - } - if atomic.compare_exchange(^m._counter, expected, 1) == 0 { - return false; - } - atomic.store(^m._owner, thread_id); - } - m._recursion++; - return true; -} -mutex_unlock :: proc(m: ^Mutex) { - recursion: i32; - thread_id := current_thread_id(); - assert(thread_id == atomic.load(^m._owner)); - - m._recursion--; - recursion = m._recursion; - if recursion == 0 { - atomic.store(^m._owner, thread_id); - } - - if atomic.fetch_add(^m._counter, -1) > 1 { - if recursion == 0 { - semaphore_release(^m._semaphore); - } - } -} - +#load "sync_windows.odin" when ODIN_OS == "windows"; +#load "sync_linux.odin" when ODIN_OS == "linux"; diff --git a/odin.exe b/odin.exe index 48f24a8bd..dfe8a37cc 100644 Binary files a/odin.exe and b/odin.exe differ diff --git a/src/build_settings.c b/src/build_settings.c index 6d7dbe939..fdae48dd3 100644 --- a/src/build_settings.c +++ b/src/build_settings.c @@ -144,7 +144,7 @@ String odin_root_dir(void) { Array(char) path_buf; isize len, i; gbTempArenaMemory tmp; - wchar_t *text; + u8 *text; if (global_module_path_set) { return global_module_path; @@ -212,11 +212,10 @@ String path_to_fullpath(gbAllocator a, String s) { } #elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) String path_to_fullpath(gbAllocator a, String s) { - char* p = realpath(s.text, 0); - // GB_ASSERT(p && "file does not exist"); - if(!p) return make_string_c(""); + char *p = realpath(cast(char *)s.text, 0); + if(p == NULL) return make_string_c(""); - return make_string(p, strlen(p)); + return make_string_c(p); } #else #error Implement system diff --git a/src/check_expr.c b/src/check_expr.c index 546ec608e..0f231b9cf 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -580,7 +580,7 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena); - MapEntity entity_map = {0}; + MapEntity entity_map = {0}; // Key: String map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*variant_count); Entity *using_index_expr = NULL; @@ -593,6 +593,12 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node) { field_count = check_fields(c, NULL, ut->fields, fields, field_count, str_lit("union")); + for (isize i = 0; i < field_count; i++) { + Entity *f = fields[i]; + String name = f->token.string; + map_entity_set(&entity_map, hash_string(name), f); + } + union_type->Record.fields = fields; union_type->Record.field_count = field_count; @@ -2324,10 +2330,10 @@ void check_cast(Checker *c, Operand *x, Type *type) { } } } else if (check_is_castable_to(c, x, type)) { - can_convert = true; - if (x->mode != Addressing_Constant || is_type_any(type)) { + if (x->mode != Addressing_Constant) { x->mode = Addressing_Value; } + can_convert = true; } if (!can_convert) { @@ -2348,9 +2354,7 @@ void check_cast(Checker *c, Operand *x, Type *type) { if (is_const_expr && !is_type_constant_type(type)) { final_type = default_type(x->type); } - if (!is_type_any(final_type)) { - update_expr_type(c, x->expr, final_type, true); - } + update_expr_type(c, x->expr, final_type, true); } x->type = type; @@ -5166,10 +5170,15 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t } for (; index < elem_count; index++) { + GB_ASSERT(cl->elems.e != NULL); AstNode *e = cl->elems.e[index]; + if (e == NULL) { + error_node(node, "Invalid literal element"); + continue; + } + if (e->kind == AstNode_FieldValue) { - error_node(e, - "`field = value` is only allowed in struct literals"); + error_node(e, "`field = value` is only allowed in struct literals"); continue; } @@ -5351,7 +5360,6 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t switch (ce->token.kind) { case Token_cast: check_cast(c, o, t); - o->expr = node; break; case Token_transmute: { if (o->mode == Addressing_Constant) { @@ -5462,8 +5470,6 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t default: GB_PANIC("Unknown cast expression"); } - - o->expr = node; case_end; diff --git a/src/common.c b/src/common.c index fe07dc175..3234bc59c 100644 --- a/src/common.c +++ b/src/common.c @@ -2,6 +2,7 @@ #define GB_IMPLEMENTATION #include "gb/gb.h" + #include gbAllocator heap_allocator(void) { diff --git a/src/gb/gb.h b/src/gb/gb.h index 892926a40..cad436640 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -278,6 +278,7 @@ extern "C" { // #include #if !defined(GB_SYSTEM_WINDOWS) #include + #include #endif @@ -315,6 +316,10 @@ extern "C" { #include #include #include + + #if defined(GB_CPU_X86) + #include + #endif #endif #if defined(GB_SYSTEM_OSX) @@ -3646,15 +3651,15 @@ gb_inline void *gb_memcopy(void *dest, void const *source, isize n) { #if defined(_MSC_VER) // TODO(bill): Is this good enough? __movsb(cast(u8 *)dest, cast(u8 *)source, n); -#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) +// #elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX) // NOTE(zangent): I assume there's a reason this isn't being used elsewhere, // but casting pointers as arguments to an __asm__ call is considered an // error on MacOS and (I think) Linux // TODO(zangent): Figure out how to refactor the asm code so it works on MacOS, // since this is probably not the way the author intended this to work. - memcpy(dest, source, n); + // memcpy(dest, source, n); #elif defined(GB_CPU_X86) - __asm__ __volatile__("rep movsb" : "+D"(cast(u8 *)dest), "+S"(cast(u8 *)source), "+c"(n) : : "memory"); + __asm__ __volatile__("rep movsb" : "+D"(dest), "+S"(source), "+c"(n) : : "memory"); #else u8 *d = cast(u8 *)dest; u8 const *s = cast(u8 const *)source; @@ -4849,6 +4854,26 @@ GB_ALLOCATOR_PROC(gb_heap_allocator_proc) { case gbAllocation_Resize: ptr = _aligned_realloc(old_memory, size, alignment); break; + +#elif defined(GB_SYSTEM_LINUX) + // TODO(bill): *nix version that's decent + case gbAllocation_Alloc: { + // ptr = aligned_alloc(alignment, size); + ptr = malloc(size+alignment); + + if (flags & gbAllocatorFlag_ClearToZero) { + gb_zero_size(ptr, size); + } + } break; + + case gbAllocation_Free: { + free(old_memory); + } break; + + case gbAllocation_Resize: { + ptr = realloc(old_memory, size); + // ptr = gb_default_resize_align(gb_heap_allocator(), old_memory, old_size, size, alignment); + } break; #else // TODO(bill): *nix version that's decent case gbAllocation_Alloc: { @@ -4864,8 +4889,7 @@ GB_ALLOCATOR_PROC(gb_heap_allocator_proc) { } break; case gbAllocation_Resize: { - gbAllocator a = gb_heap_allocator(); - ptr = gb_default_resize_align(a, old_memory, old_size, size, alignment); + ptr = gb_default_resize_align(gb_heap_allocator(), old_memory, old_size, size, alignment); } break; #endif @@ -7595,7 +7619,10 @@ gbFileError gb_file_close(gbFile *f) { return gbFileError_Invalid; } - if (f->filename) gb_free(gb_heap_allocator(), cast(char *)f->filename); + // + // TODO HACK(bill): Memory Leak!!! + // if (f->filename) gb_free(gb_heap_allocator(), cast(char *)f->filename); + // #if defined(GB_SYSTEM_WINDOWS) if (f->fd.p == INVALID_HANDLE_VALUE) { diff --git a/src/ir.c b/src/ir.c index c9e42af19..946e219dd 100644 --- a/src/ir.c +++ b/src/ir.c @@ -548,6 +548,8 @@ typedef struct irGen { irModule module; gbFile output_file; bool opt_called; + String output_base; + String output_name; } irGen; @@ -6650,9 +6652,13 @@ bool ir_gen_init(irGen *s, Checker *c) { ir_init_module(&s->module, c); // s->module.generate_debug_info = false; + String init_fullpath = c->parser->init_fullpath; // TODO(bill): generate appropriate output name - int pos = cast(int)string_extension_position(c->parser->init_fullpath); - gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, c->parser->init_fullpath.text)); + int pos = cast(int)string_extension_position(init_fullpath); + int dir_pos = cast(int)string_extension_position(init_fullpath); + s->output_name = filename_from_path(init_fullpath); + s->output_base = make_string(init_fullpath.text, pos); + gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, init_fullpath.text)); if (err != gbFileError_None) { return false; } @@ -6792,12 +6798,6 @@ void ir_gen_tree(irGen *s) { } else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) { // Handle later } else if (scope->is_init && e->kind == Entity_Procedure && str_eq(name, str_lit("main"))) { - #ifdef GB_SYSTEM_OSX - } else if (str_eq(name, str_lit("args")) && str_eq(e->token.pos.file, get_fullpath_core(heap_allocator(), str_lit("os_x.odin")))) { - #endif - #ifdef GB_SYSTEM_LINUX - } else if (str_eq(name, str_lit("args")) && str_eq(e->token.pos.file, get_fullpath_core(heap_allocator(), str_lit("os_linux.odin")))) { - #endif } else { name = ir_mangle_name(s, e->token.pos.file, e); } @@ -7227,11 +7227,6 @@ void ir_gen_tree(irGen *s) { tag = ir_emit_conv(proc, ti_ptr, t_type_info_tuple_ptr); irValue *record = ir_emit_struct_ep(proc, tag, 2); - { - irValue *align = ir_const_int(a, type_align_of(a, t)); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), align); - } - irValue *memory_types = ir_type_info_member_types_offset(proc, t->Tuple.variable_count); irValue *memory_names = ir_type_info_member_names_offset(proc, t->Tuple.variable_count); @@ -7261,16 +7256,12 @@ void ir_gen_tree(irGen *s) { irValue *record = ir_emit_struct_ep(proc, tag, 2); { - irValue *size = ir_const_int(a, type_size_of(a, t)); - irValue *align = ir_const_int(a, type_align_of(a, t)); irValue *packed = ir_const_bool(a, t->Record.is_packed); irValue *ordered = ir_const_bool(a, t->Record.is_ordered); irValue *custom_align = ir_const_bool(a, t->Record.custom_align); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 3), size); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), align); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 5), packed); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 6), ordered); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 7), custom_align); + ir_emit_store(proc, ir_emit_struct_ep(proc, record, 3), packed); + ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), ordered); + ir_emit_store(proc, ir_emit_struct_ep(proc, record, 5), custom_align); } irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count); @@ -7375,13 +7366,6 @@ void ir_gen_tree(irGen *s) { tag = ir_emit_conv(proc, ti_ptr, t_type_info_raw_union_ptr); irValue *record = ir_emit_struct_ep(proc, tag, 2); - { - irValue *size = ir_const_int(a, type_size_of(a, t)); - irValue *align = ir_const_int(a, type_align_of(a, t)); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 3), size); - ir_emit_store(proc, ir_emit_struct_ep(proc, record, 4), align); - } - irValue *memory_types = ir_type_info_member_types_offset(proc, t->Record.field_count); irValue *memory_names = ir_type_info_member_names_offset(proc, t->Record.field_count); irValue *memory_offsets = ir_type_info_member_offsets_offset(proc, t->Record.field_count); diff --git a/src/ir_print.c b/src/ir_print.c index 22a575437..6bb20aaaf 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -1386,7 +1386,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) { void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { -#ifndef GB_SYSTEM_WINDOWS +// #ifndef GB_SYSTEM_WINDOWS +#if 0 bool is_main_proc = proc->parent == NULL && str_eq(proc->name, str_lit("main")); AstFile fake_file; @@ -1541,8 +1542,9 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) { ir_fprintf(f, " "); -#ifndef GB_SYSTEM_WINDOWS - if(uses_args) +// #ifndef GB_SYSTEM_WINDOWS +#if 0 + if(uses_args) ir_fprintf(f, "@.nix_argpatch_main"); else #endif @@ -1713,6 +1715,7 @@ void print_llvm_ir(irGen *ir) { if (scope != NULL) { // TODO(bill): Fix this rule. What should it be? in_global_scope = scope->is_global || scope->is_init; + // in_global_scope = value->Global.name_is_not_mangled; } ir_print_encoded_global(f, ir_get_global_name(m, v), in_global_scope); diff --git a/src/main.c b/src/main.c index ccc2b4c3b..268324949 100644 --- a/src/main.c +++ b/src/main.c @@ -107,7 +107,7 @@ i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) { // } // exit_code = status; - + return exit_code; } #endif @@ -249,9 +249,9 @@ int main(int argc, char **argv) { #if 1 timings_start_section(&timings, str_lit("llvm-opt")); - char const *output_name = ir_gen.output_file.filename; - isize base_name_len = gb_path_extension(output_name)-1 - output_name; - String output = make_string(cast(u8 *)output_name, base_name_len); + String output_name = ir_gen.output_name; + String output_base = ir_gen.output_base; + int base_name_len = output_base.len; i32 optimization_level = 0; optimization_level = gb_clamp(optimization_level, 0, 3); @@ -261,7 +261,7 @@ int main(int argc, char **argv) { #if defined(GB_SYSTEM_WINDOWS) // For more passes arguments: http://llvm.org/docs/Passes.html exit_code = system_exec_command_line_app("llvm-opt", false, - "\"%.*sbin/opt\" \"%s\" -o \"%.*s\".bc " + "\"%.*sbin/opt\" \"%.*s\".ll -o \"%.*s\".bc " "-mem2reg " "-memcpyopt " "-die " @@ -270,7 +270,7 @@ int main(int argc, char **argv) { // "-S " "", LIT(build_context.ODIN_ROOT), - output_name, LIT(output)); + LIT(output_base), LIT(output_base)); if (exit_code != 0) { return exit_code; } @@ -278,7 +278,7 @@ int main(int argc, char **argv) { // NOTE(zangent): This is separate because it seems that LLVM tools are packaged // with the Windows version, while they will be system-provided on MacOS and GNU/Linux exit_code = system_exec_command_line_app("llvm-opt", false, - "opt \"%s\" -o \"%.*s\".bc " + "opt \"%.*s\".ll -o \"%.*s\".bc " "-mem2reg " "-memcpyopt " "-die " @@ -292,7 +292,7 @@ int main(int argc, char **argv) { // "-dce " // "-S " "", - output_name, LIT(output)); + LIT(output_base), LIT(output_base)); if (exit_code != 0) { return exit_code; } @@ -307,7 +307,7 @@ int main(int argc, char **argv) { // "-debug-pass=Arguments " "", LIT(build_context.ODIN_ROOT), - LIT(output), + LIT(output_base), optimization_level, LIT(build_context.llc_flags)); if (exit_code != 0) { @@ -343,7 +343,7 @@ int main(int argc, char **argv) { " %.*s " " %s " "", - LIT(output), LIT(output), output_ext, + LIT(output_base), LIT(output_base), output_ext, lib_str, LIT(build_context.link_flags), link_settings ); @@ -354,7 +354,7 @@ int main(int argc, char **argv) { // timings_print_all(&timings); if (run_output) { - system_exec_command_line_app("odin run", false, "%.*s.exe", cast(int)base_name_len, output_name); + system_exec_command_line_app("odin run", false, "%.*s.exe", LIT(output_base)); } #else @@ -369,7 +369,7 @@ int main(int argc, char **argv) { "%.*s " // "-debug-pass=Arguments " "", - LIT(output), + LIT(output_base), optimization_level, LIT(build_context.llc_flags)); if (exit_code != 0) { @@ -430,7 +430,7 @@ int main(int argc, char **argv) { // It probably has to do with including the entire CRT, but // that's quite a complicated issue to solve while remaining distro-agnostic. // Clang can figure out linker flags for us, and that's good enough _for now_. - linker = "clang"; + linker = "clang -Wno-unused-command-line-argument"; #endif exit_code = system_exec_command_line_app("ld-link", true, @@ -446,7 +446,7 @@ int main(int argc, char **argv) { // This points the linker to where the entry point is " -e _main " #endif - , linker, LIT(output), LIT(output), output_ext, + , linker, LIT(output_base), LIT(output_base), output_ext, lib_str, LIT(build_context.link_flags), link_settings ); @@ -457,7 +457,7 @@ int main(int argc, char **argv) { // timings_print_all(&timings); if (run_output) { - system_exec_command_line_app("odin run", false, "%.*s", cast(int)base_name_len, output_name); + system_exec_command_line_app("odin run", false, "%.*s", LIT(output_base)); } #endif diff --git a/src/ssa.c b/src/ssa.c index 2ed9d59f9..e7916317d 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -1916,9 +1916,9 @@ void ssa_print_exact_value(gbFile *f, ssaValue *v) { break; case ExactValue_Integer: if (is_type_unsigned(t)) { - gb_fprintf(f, " [%llu]", ev.value_integer); + gb_fprintf(f, " [%llu]", cast(unsigned long long)ev.value_integer); } else { - gb_fprintf(f, " [%lld]", ev.value_integer); + gb_fprintf(f, " [%lld]", cast(long long)ev.value_integer); } break; case ExactValue_Float: @@ -1929,7 +1929,7 @@ void ssa_print_exact_value(gbFile *f, ssaValue *v) { } else if (is_type_f64(t)) { f64 fp = cast(f64)ev.value_float; u64 x = *cast(u64 *)&fp; - gb_fprintf(f, " [0x%llx]", x); + gb_fprintf(f, " [0x%llx]", cast(unsigned long long)x); } else { GB_PANIC("unhandled integer"); } @@ -1938,7 +1938,7 @@ void ssa_print_exact_value(gbFile *f, ssaValue *v) { gb_fprintf(f, " [%.*s]", LIT(ev.value_string)); break; case ExactValue_Pointer: - gb_fprintf(f, " [0x%llx]", ev.value_pointer); + gb_fprintf(f, " [0x%llx]", cast(unsigned long long)cast(uintptr)ev.value_pointer); break; } } diff --git a/src/string.c b/src/string.c index 19161de93..139a46138 100644 --- a/src/string.c +++ b/src/string.c @@ -188,6 +188,22 @@ bool string_contains_char(String s, u8 c) { return false; } +String filename_from_path(String s) { + isize i = string_extension_position(s); + if (i > 0) { + isize j = 0; + s.len = i; + for (j = i-1; j >= 0; j--) { + if (s.text[j] == '/' || + s.text[j] == '\\') { + break; + } + } + s.text += j+1; + s.len = i-j-1; + } + return make_string(NULL, 0); +} @@ -207,7 +223,7 @@ bool string_contains_char(String s, u8 c) { #include - int convert_multibyte_to_widechar(char *multibyte_input, int input_length, wchar_t *output, int output_size) { + int convert_multibyte_to_widechar(char *multibyte_input, usize input_length, wchar_t *output, usize output_size) { iconv_t conv = iconv_open("WCHAR_T", "UTF-8"); size_t result = iconv(conv, cast(char **)&multibyte_input, &input_length, cast(char **)&output, &output_size); iconv_close(conv); @@ -215,7 +231,7 @@ bool string_contains_char(String s, u8 c) { return (int) result; } - int convert_widechar_to_multibyte(wchar_t* widechar_input, int input_length, char* output, int output_size) { + int convert_widechar_to_multibyte(wchar_t* widechar_input, usize input_length, char* output, usize output_size) { iconv_t conv = iconv_open("UTF-8", "WCHAR_T"); size_t result = iconv(conv, (char**) &widechar_input, &input_length, (char**) &output, &output_size); iconv_close(conv); diff --git a/src/tokenizer.c b/src/tokenizer.c index b800a1273..44a3b4e82 100644 --- a/src/tokenizer.c +++ b/src/tokenizer.c @@ -414,7 +414,7 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) { TokenizerInitError err = TokenizerInit_None; char *c_str = gb_alloc_array(heap_allocator(), char, fullpath.len+1); - memcpy(c_str, fullpath.text, fullpath.len); + gb_memcopy(c_str, fullpath.text, fullpath.len); c_str[fullpath.len] = '\0'; // TODO(bill): Memory map rather than copy contents diff --git a/src/types.c b/src/types.c index 773ef5efe..a12432747 100644 --- a/src/types.c +++ b/src/types.c @@ -2058,12 +2058,12 @@ gbString write_type_to_string(gbString str, Type *type) { break; case Type_Array: - str = gb_string_appendc(str, gb_bprintf("[%lld]", type->Array.count)); + str = gb_string_appendc(str, gb_bprintf("[%d]", cast(int)type->Array.count)); str = write_type_to_string(str, type->Array.elem); break; case Type_Vector: - str = gb_string_appendc(str, gb_bprintf("[vector %lld]", type->Vector.count)); + str = gb_string_appendc(str, gb_bprintf("[vector %d]", cast(int)type->Vector.count)); str = write_type_to_string(str, type->Vector.elem); break; @@ -2177,7 +2177,7 @@ gbString write_type_to_string(gbString str, Type *type) { case Type_Map: { str = gb_string_appendc(str, "map["); if (type->Map.count > 0) { - str = gb_string_appendc(str, gb_bprintf("%lld, ", type->Map.count)); + str = gb_string_appendc(str, gb_bprintf("%d, ", cast(int)type->Map.count)); } str = write_type_to_string(str, type->Map.key); str = gb_string_appendc(str, "]");