oh boy, basic osx/unix support

This commit is contained in:
zhiayang
2017-02-02 04:20:33 +08:00
parent 502e63b9c5
commit 864310e3da
16 changed files with 559 additions and 75 deletions
+92
View File
@@ -22,6 +22,7 @@ typedef struct BuildContext {
String const WIN32_SEPARATOR_STRING = {cast(u8 *)"\\", 1};
String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1};
#if defined(WINDOWS)
String odin_root_dir(void) {
String path = global_module_path;
Array(wchar_t) path_buf;
@@ -71,6 +72,83 @@ String odin_root_dir(void) {
return path;
}
#elif defined(GB_SYSTEM_OSX)
#include <mach-o/dyld.h>
String odin_root_dir(void) {
String path = global_module_path;
Array(char) path_buf;
isize len, i;
gbTempArenaMemory tmp;
wchar_t *text;
if (global_module_path_set) {
return global_module_path;
}
array_init_count(&path_buf, heap_allocator(), 300);
len = 0;
for (;;) {
int sz = path_buf.count;
int res = _NSGetExecutablePath(&path_buf.e[0], &sz);
if(res == 0) {
len = sz;
break;
} else {
array_resize(&path_buf, sz + 1);
}
}
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
text = gb_alloc_array(string_buffer_allocator, u8, len + 1);
gb_memmove(text, &path_buf.e[0], len);
path = make_string(text, len);
for (i = path.len-1; i >= 0; i--) {
u8 c = path.text[i];
if (c == '/' || c == '\\') {
break;
}
path.len--;
}
global_module_path = path;
global_module_path_set = true;
gb_temp_arena_memory_end(tmp);
// array_free(&path_buf);
return path;
}
#else
#error Implement system
#endif
#if defined(GB_SYSTEM_WINDOWS)
String path_to_fullpath(gbAllocator a, String s) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
String16 string16 = string_to_string16(string_buffer_allocator, s);
@@ -86,6 +164,17 @@ String path_to_fullpath(gbAllocator a, String s) {
gb_temp_arena_memory_end(tmp);
return result;
}
#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("");
return make_string(p, strlen(p));
}
#else
#error Implement system
#endif
String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
@@ -154,6 +243,9 @@ void init_build_context(BuildContext *bc) {
#if defined(GB_SYSTEM_WINDOWS)
bc->ODIN_OS = str_lit("windows");
bc->ODIN_ARCH = str_lit("amd64");
#elif defined(GB_SYSTEM_OSX)
bc->ODIN_OS = str_lit("osx");
bc->ODIN_ARCH = str_lit("amd64");
#else
#error Implement system
#endif
+1 -1
View File
@@ -69,7 +69,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
AstNode *rhs = inits.e[i];
Operand o = {0};
check_multi_expr(c, &o, rhs);
if (o.type->kind != Type_Tuple) {
if (o.type == NULL || o.type->kind != Type_Tuple) {
array_add(&operands, o);
} else {
TypeTuple *tuple = &o.type->Tuple;
+5 -1
View File
@@ -225,6 +225,9 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) {
return -1;
}
#ifndef _MAX
#define _MAX(x, y) ((x) > (y) ? (x) : (y))
#endif
bool check_is_assignable_to_with_score(Checker *c, Operand *operand, Type *type, i64 *score_) {
i64 score = 0;
@@ -232,7 +235,8 @@ bool check_is_assignable_to_with_score(Checker *c, Operand *operand, Type *type,
bool ok = distance >= 0;
if (ok) {
// TODO(bill): A decent score function
score = max(1000000 - distance*distance, 0);
// score = max(1000000 - distance*distance, 0);
score = _MAX(1000000 - distance*distance, 0);
}
if (score_) *score_ = score;
return ok;
+1
View File
@@ -724,6 +724,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
skip_expr:
; // again, declaring a variable immediately after a label... weird.
AstNode *lhs[2] = {rs->value, rs->index};
Type * rhs[2] = {val, idx};
-48
View File
@@ -118,47 +118,6 @@ typedef enum StmtFlag {
Stmt_GiveAllowed = 1<<3,
} StmtFlag;
typedef enum BuiltinProcId {
BuiltinProc_Invalid,
BuiltinProc_new,
BuiltinProc_new_slice,
BuiltinProc_free,
BuiltinProc_reserve,
BuiltinProc_append,
BuiltinProc_size_of,
BuiltinProc_size_of_val,
BuiltinProc_align_of,
BuiltinProc_align_of_val,
BuiltinProc_offset_of,
BuiltinProc_offset_of_val,
BuiltinProc_type_of_val,
BuiltinProc_type_info,
BuiltinProc_type_info_of_val,
BuiltinProc_compile_assert,
BuiltinProc_assert,
BuiltinProc_panic,
BuiltinProc_copy,
// BuiltinProc_append,
BuiltinProc_swizzle,
// BuiltinProc_ptr_offset,
// BuiltinProc_ptr_sub,
BuiltinProc_slice_ptr,
BuiltinProc_min,
BuiltinProc_max,
BuiltinProc_abs,
BuiltinProc_clamp,
BuiltinProc_Count,
} BuiltinProcId;
typedef struct BuiltinProc {
String name;
isize arg_count;
@@ -205,13 +164,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("clamp"), 3, false, Expr_Expr},
};
typedef enum ImplicitValueId {
ImplicitValue_Invalid,
ImplicitValue_context,
ImplicitValue_Count,
} ImplicitValueId;
typedef struct ImplicitValueInfo {
String name;
String backing_name;
+59 -2
View File
@@ -1,8 +1,65 @@
typedef struct Scope Scope;
typedef struct Checker Checker;
typedef struct Type Type;
typedef enum BuiltinProcId BuiltinProcId;
typedef enum ImplicitValueId ImplicitValueId;
// typedef enum BuiltinProcId BuiltinProcId;
// typedef enum ImplicitValueId ImplicitValueId;
typedef enum BuiltinProcId {
BuiltinProc_Invalid,
BuiltinProc_new,
BuiltinProc_new_slice,
BuiltinProc_free,
BuiltinProc_reserve,
BuiltinProc_append,
BuiltinProc_size_of,
BuiltinProc_size_of_val,
BuiltinProc_align_of,
BuiltinProc_align_of_val,
BuiltinProc_offset_of,
BuiltinProc_offset_of_val,
BuiltinProc_type_of_val,
BuiltinProc_type_info,
BuiltinProc_type_info_of_val,
BuiltinProc_compile_assert,
BuiltinProc_assert,
BuiltinProc_panic,
BuiltinProc_copy,
// BuiltinProc_append,
BuiltinProc_swizzle,
// BuiltinProc_ptr_offset,
// BuiltinProc_ptr_sub,
BuiltinProc_slice_ptr,
BuiltinProc_min,
BuiltinProc_max,
BuiltinProc_abs,
BuiltinProc_clamp,
BuiltinProc_Count,
} BuiltinProcId;
typedef enum ImplicitValueId {
ImplicitValue_Invalid,
ImplicitValue_context,
ImplicitValue_Count,
} ImplicitValueId;
#define ENTITY_KINDS \
ENTITY_KIND(Invalid) \
+1
View File
@@ -416,6 +416,7 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
}
error:
; // MSVC accepts this??? apparently you cannot declare variables immediately after labels...
ExactValue error_value = {0};
// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op));
return error_value;
+20 -3
View File
@@ -276,6 +276,8 @@ extern "C" {
#include <stdarg.h>
#include <stddef.h>
#if defined(GB_SYSTEM_WINDOWS)
#if !defined(GB_NO_WINDOWS_H)
#define NOMINMAX 1
@@ -296,6 +298,7 @@ extern "C" {
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#define _IOSC11_SOURCE
#include <stdlib.h> // NOTE(bill): malloc on linux
#include <sys/mman.h>
#if !defined(GB_SYSTEM_OSX)
@@ -4819,14 +4822,17 @@ GB_ALLOCATOR_PROC(gb_heap_allocator_proc) {
#else
// TODO(bill): *nix version that's decent
case gbAllocation_Alloc: {
ptr = aligned_alloc(alignment, size);
// ptr = aligned_alloc(alignment, size);
posix_memalign(&ptr, alignment, size);
if (flags & gbAllocatorFlag_ClearToZero) {
gb_zero_size(ptr, size);
}
} break;
case gbAllocation_Free: {
free(gb_allocation_header(old_memory));
// free(old_memory);
} break;
case gbAllocation_Resize: {
@@ -7754,7 +7760,18 @@ char *gb_path_get_full_name(gbAllocator a, char const *path) {
return gb_alloc_str_len(a, buf, len+1);
#else
// TODO(bill): Make work on *nix, etc.
return gb_alloc_str_len(a, path, gb_strlen(path));
char* p = realpath(path, 0);
GB_ASSERT(p && "file does not exist");
isize len = gb_strlen(p);
// bill... gb_alloc_str_len refused to work for this...
char* ret = gb_alloc(a, sizeof(char) * len + 1);
gb_memmove(ret, p, len);
ret[len] = 0;
free(p);
return ret;
#endif
}
+56 -7
View File
@@ -16,8 +16,10 @@ extern "C" {
#include "ir_print.c"
// #include "vm.c"
#if defined(GB_SYSTEM_WINDOWS)
// NOTE(bill): `name` is used in debugging and profiling modes
i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)};
PROCESS_INFORMATION pi = {0};
char cmd_line[4096] = {0};
@@ -59,6 +61,53 @@ i32 win32_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
gb_temp_arena_memory_end(tmp);
return exit_code;
}
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
i32 system_exec_command_line_app(char *name, bool is_silent, char *fmt, ...) {
char cmd_line[4096] = {0};
isize cmd_len;
va_list va;
String cmd;
i32 exit_code = 0;
va_start(va, fmt);
cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
va_end(va);
exit_code = system(cmd.text);
// pid_t pid = fork();
// int status = 0;
// if(pid == 0) {
// // in child, pid == 0.
// int ret = execvp(cmd.text, (char* const*) cmd.text);
// if(ret == -1) {
// gb_printf_err("Failed to execute command:\n\t%s\n", cmd_line);
// // we're in the child, so returning won't do us any good -- just quit.
// exit(-1);
// }
// // unreachable
// abort();
// } else {
// // wait for child to finish, then we can continue cleanup
// int s = 0;
// waitpid(pid, &s, 0);
// status = WEXITSTATUS(s);
// }
// exit_code = status;
}
#endif
void print_usage_line(i32 indent, char *fmt, ...) {
while (indent --> 0) {
@@ -190,7 +239,7 @@ int main(int argc, char **argv) {
// prof_print_all();
#if 1
#if 1
timings_start_section(&timings, str_lit("llvm-opt"));
char const *output_name = ir_gen.output_file.filename;
@@ -202,7 +251,7 @@ int main(int argc, char **argv) {
i32 exit_code = 0;
// For more passes arguments: http://llvm.org/docs/Passes.html
exit_code = win32_exec_command_line_app("llvm-opt", false,
exit_code = system_exec_command_line_app("llvm-opt", false,
"\"%.*sbin/opt\" \"%s\" -o \"%.*s\".bc "
"-mem2reg "
"-memcpyopt "
@@ -217,10 +266,10 @@ int main(int argc, char **argv) {
return exit_code;
}
#if 1
#if 0
timings_start_section(&timings, str_lit("llvm-llc"));
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
exit_code = win32_exec_command_line_app("llvm-llc", false,
exit_code = system_exec_command_line_app("llvm-llc", false,
"\"%.*sbin/llc\" \"%.*s.bc\" -filetype=obj -O%d "
"%.*s "
// "-debug-pass=Arguments "
@@ -255,7 +304,7 @@ int main(int argc, char **argv) {
link_settings = "/ENTRY:mainCRTStartup";
}
exit_code = win32_exec_command_line_app("msvc-link", true,
exit_code = system_exec_command_line_app("msvc-link", true,
"link \"%.*s\".obj -OUT:\"%.*s.%s\" %s "
"/defaultlib:libcmt "
"/nologo /incremental:no /opt:ref /subsystem:CONSOLE "
@@ -273,7 +322,7 @@ int main(int argc, char **argv) {
// timings_print_all(&timings);
if (run_output) {
win32_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", cast(int)base_name_len, output_name);
}
#endif
#endif
+1
View File
@@ -3785,6 +3785,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) {
String import_rel_path = imported_file.rel_path;
TokenPos pos = imported_file.pos;
AstFile file = {0};
ParseFileError err = init_ast_file(&file, import_path);
if (err != ParseFile_None) {
+52 -9
View File
@@ -165,6 +165,54 @@ bool string_contains_char(String s, u8 c) {
return false;
}
#if defined(GB_SYSTEM_WINDOWS)
int convert_multibyte_to_widechar(char* multibyte_input, int input_length, wchar_t* output, int output_size)
{
return MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, multibyte_input, input_length, output, output_size);
}
int convert_widechar_to_multibyte(wchar_t* widechar_input, int input_length, char* output, int output_size)
{
return WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, widechar_input, input_length, output, output_size, NULL, NULL);
}
}
#elif defined(GB_SYSTEM_UNIX) || defined(GB_SYSTEM_OSX)
#include <iconv.h>
int convert_multibyte_to_widechar(char* multibyte_input, int input_length, wchar_t* output, int output_size)
{
iconv_t conv = iconv_open("WCHAR_T", "UTF-8");
size_t result = iconv(conv, (char**) &multibyte_input, &input_length, (char**) &output, &output_size);
iconv_close(conv);
return (int) result;
}
int convert_widechar_to_multibyte(wchar_t* widechar_input, int input_length, char* output, int 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);
return (int) result;
}
#else
#error Implement system
#endif
// TODO(bill): Make this non-windows specific
String16 string_to_string16(gbAllocator a, String s) {
int len, len1;
@@ -174,16 +222,14 @@ String16 string_to_string16(gbAllocator a, String s) {
return make_string16(NULL, 0);
}
len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, NULL, 0);
len = convert_multibyte_to_widechar(cast(char *)s.text, s.len, NULL, 0);
if (len == 0) {
return make_string16(NULL, 0);
}
text = gb_alloc_array(a, wchar_t, len+1);
len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, text, len);
len1 = convert_multibyte_to_widechar(cast(char *)s.text, s.len, text, len);
if (len1 == 0) {
gb_free(a, text);
return make_string16(NULL, 0);
@@ -201,16 +247,14 @@ String string16_to_string(gbAllocator a, String16 s) {
return make_string(NULL, 0);
}
len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, NULL, 0, NULL, NULL);
len = convert_widechar_to_multibyte(s.text, s.len, NULL, 0);
if (len == 0) {
return make_string(NULL, 0);
}
text = gb_alloc_array(a, u8, len+1);
len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, cast(char *)text, len, NULL, NULL);
len1 = convert_widechar_to_multibyte(s.text, s.len, cast(char *)text, len);
if (len1 == 0) {
gb_free(a, text);
return make_string(NULL, 0);
@@ -236,7 +280,6 @@ String string16_to_string(gbAllocator a, String16 s) {
bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *tail_string) {
u8 c;
+36
View File
@@ -11,6 +11,7 @@ typedef struct Timings {
} Timings;
#if defined(GB_SYSTEM_WINDOWS)
u64 win32_time_stamp_time_now(void) {
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
@@ -26,10 +27,43 @@ u64 win32_time_stamp__freq(void) {
return win32_perf_count_freq.QuadPart;
}
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
#include <time.h>
u64 unix_time_stamp_time_now(void) {
struct timespec ts;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts);
return (ts.tv_sec * 1000000000) + ts.tv_nsec;
}
u64 unix_time_stamp__freq(void) {
gb_local_persist u64 freq = 0;
if (freq == 0) {
struct timespec ts;
clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts);
// that would be an absurd resolution (or lack thereof)
GB_ASSERT(ts.tv_sec == 0);
freq = cast(u64) ((1.0 / ts.tv_nsec) * 1000000000.0);
GB_ASSERT(freq != 0);
}
return freq;
}
#else
#error Implement system
#endif
u64 time_stamp_time_now(void) {
#if defined(GB_SYSTEM_WINDOWS)
return win32_time_stamp_time_now();
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
return unix_time_stamp_time_now();
#else
#error time_stamp_time_now
#endif
@@ -38,6 +72,8 @@ u64 time_stamp_time_now(void) {
u64 time_stamp__freq(void) {
#if defined(GB_SYSTEM_WINDOWS)
return win32_time_stamp__freq();
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
return unix_time_stamp__freq();
#else
#error time_stamp__freq
#endif
+1 -1
View File
@@ -1343,7 +1343,7 @@ void type_path_pop(TypePath *tp) {
i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t);
i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, i64 index);
i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, isize index);
i64 type_size_of_internal (BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path);
i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypePath *path);