Bladeren bron

Basic Linux Build!

Ginger Bill 8 jaren geleden
bovenliggende
commit
aaf355e750
17 gewijzigde bestanden met toevoegingen van 212 en 274 verwijderingen
  1. 5 4
      core/_preload.odin
  2. 9 10
      core/fmt.odin
  3. 1 0
      core/opengl.odin
  4. 82 92
      core/os_linux.odin
  5. 2 91
      core/sync.odin
  6. BIN
      odin.exe
  7. 4 5
      src/build_settings.c
  8. 17 11
      src/check_expr.c
  9. 1 0
      src/common.c
  10. 33 6
      src/gb/gb.h
  11. 11 27
      src/ir.c
  12. 6 3
      src/ir_print.c
  13. 15 15
      src/main.c
  14. 4 4
      src/ssa.c
  15. 18 2
      src/string.c
  16. 1 1
      src/tokenizer.c
  17. 3 3
      src/types.c

+ 5 - 4
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();

+ 9 - 10
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;

+ 1 - 0
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";

+ 82 - 92
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));
-
-	// We have a file!
+	defer close(fd);
 
-	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;
 }

+ 2 - 91
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";

BIN
odin.exe


+ 4 - 5
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

+ 17 - 11
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;
 
 

+ 1 - 0
src/common.c

@@ -2,6 +2,7 @@
 #define GB_IMPLEMENTATION
 #include "gb/gb.h"
 
+
 #include <math.h>
 
 gbAllocator heap_allocator(void) {

+ 33 - 6
src/gb/gb.h

@@ -278,6 +278,7 @@ extern "C" {
 // #include <stdarg.h>
 #if !defined(GB_SYSTEM_WINDOWS)
 	#include <stddef.h>
+	#include <stdarg.h>
 #endif
 
 
@@ -315,6 +316,10 @@ extern "C" {
 	#include <sys/types.h>
 	#include <time.h>
 	#include <unistd.h>
+
+	#if defined(GB_CPU_X86)
+		#include <xmmintrin.h>
+	#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) {

+ 11 - 27
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);

+ 6 - 3
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);

+ 15 - 15
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

+ 4 - 4
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;
 	}
 }

+ 18 - 2
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 <iconv.h>
 
-	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);

+ 1 - 1
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

+ 3 - 3
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, "]");