Unicode file loading; push_allocator & push_context

This commit is contained in:
Ginger Bill
2016-09-23 14:59:58 +01:00
parent ee0aa7b9de
commit a31bab5aae
19 changed files with 484 additions and 172 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ set compiler_warnings= ^
-wd4505 -wd4512 -wd4550
set compiler_includes=
set libs= kernel32.lib user32.lib gdi32.lib opengl32.lib
set libs= kernel32.lib
set linker_flags= -incremental:no -opt:ref -subsystem:console
+14 -2
View File
@@ -1,19 +1,31 @@
#import "fmt.odin"
#import "os.odin"
#import "mem.odin"
// #import "http_test.odin" as ht
// #import "game.odin" as game
// #import "punity.odin" as pn
main :: proc() {
arena: mem.Arena
mem.init_arena_from_context(^arena, 1000)
defer mem.free_arena(^arena)
push_allocator mem.arena_allocator(^arena) {
x := new(int)
x^ = 1337
fmt.println(x^)
}
// struct_padding()
// bounds_checking()
// type_introspection()
// any_type()
// crazy_introspection()
namespaces_and_files()
// namespaces_and_files()
// miscellany()
// ht.run()
// game.run()
// {
-1
View File
@@ -33,4 +33,3 @@ thing :: proc() {
thing :: proc() {
println("Hello5!")
}*/
+5 -4
View File
@@ -130,6 +130,7 @@ memory_compare :: proc(dst, src: rawptr, len: int) -> int {
}
memory_copy :: proc(dst, src: rawptr, len: int) #inline {
// NOTE(bill): This _must_ implemented like C's memmove
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memmove.p0i8.p0i8.i64"
llvm_memmove_64bit(dst, src, len, 1, false)
}
@@ -142,7 +143,7 @@ memory_copy :: proc(dst, src: rawptr, len: int) #inline {
Allocator :: struct {
Allocator :: struct #ordered {
Mode :: enum {
ALLOC,
FREE,
@@ -159,7 +160,7 @@ Allocator :: struct {
}
Context :: struct {
Context :: struct #ordered {
thread_id: int
allocator: Allocator
@@ -279,8 +280,6 @@ __default_allocator :: proc() -> Allocator {
__string_eq :: proc(a, b: string) -> bool {
if a.count != b.count {
return false
@@ -382,3 +381,5 @@ __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
return ""
}
+1
View File
@@ -1,6 +1,7 @@
@echo off
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
set _NO_DEBUG_HEAP=1
+22 -4
View File
@@ -839,10 +839,9 @@ void check_type_name_cycles(Checker *c, CycleCheck *cc, Entity *e) {
// }
}
void init_type_info_types(Checker *c) {
void init_runtime_types(Checker *c) {
if (t_type_info == NULL) {
String type_info_str = make_string("Type_Info");
Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
if (e == NULL) {
compiler_error("Could not find type declaration for `Type_Info`\n"
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
@@ -875,6 +874,25 @@ void init_type_info_types(Checker *c) {
t_type_info_enum = record->fields[15]->type;
}
if (t_allocator == NULL) {
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Allocator"));
if (e == NULL) {
compiler_error("Could not find type declaration for `Allocator`\n"
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
}
t_allocator = e->type;
t_allocator_ptr = make_type_pointer(c->allocator, t_allocator);
}
if (t_context == NULL) {
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Context"));
if (e == NULL) {
compiler_error("Could not find type declaration for `Context`\n"
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
}
t_context = e->type;
t_context_ptr = make_type_pointer(c->allocator, t_context);
}
}
@@ -1131,7 +1149,7 @@ void check_parsed_files(Checker *c) {
check_global_entity(c, Entity_TypeName);
init_type_info_types(c);
init_runtime_types(c);
#if 1
check_global_entity(c, Entity_Constant);
check_global_entity(c, Entity_Procedure);
+39 -23
View File
@@ -266,15 +266,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
AstNode *name = cd->names[i];
Entity *e = entities[i];
Token name_token = name->Ident;
HashKey key = hash_string(name_token.string);
if (map_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
} else {
map_set(&entity_map, key, e);
if (name_token.string == make_string("_")) {
other_fields[other_field_index++] = e;
} else {
HashKey key = hash_string(name_token.string);
if (map_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
} else {
map_set(&entity_map, key, e);
other_fields[other_field_index++] = e;
}
add_entity(c, c->context.scope, name, e);
}
add_entity(c, c->context.scope, name, e);
}
} else if (decl->kind == AstNode_TypeDecl) {
ast_node(td, TypeDecl, decl);
@@ -284,15 +288,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
add_entity(c, c->context.scope, td->name, e);
check_type_decl(c, e, td->type, NULL, NULL);
HashKey key = hash_string(name_token.string);
if (map_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
} else {
map_set(&entity_map, key, e);
if (name_token.string == make_string("_")) {
other_fields[other_field_index++] = e;
} else {
HashKey key = hash_string(name_token.string);
if (map_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this structure", LIT(name_token.string));
} else {
map_set(&entity_map, key, e);
other_fields[other_field_index++] = e;
}
add_entity_use(&c->info, td->name, e);
}
add_entity_use(&c->info, td->name, e);
}
}
@@ -318,6 +326,11 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
type->Named.type_name = e;
add_entity(c, c->context.scope, name, e);
if (name_token.string == make_string("_")) {
error(name_token, "`_` cannot be used a union subtype");
continue;
}
HashKey key = hash_string(name_token.string);
if (map_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
@@ -352,17 +365,20 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
Token name_token = name->Ident;
Entity *e = make_entity_field(c->allocator, c->context.scope, name_token, type, vd->is_using, cast(i32)field_index);
HashKey key = hash_string(name_token.string);
if (map_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this type", LIT(name_token.string));
if (name_token.string == make_string("_")) {
fields[field_index++] = e;
} else {
map_set(&entity_map, key, e);
fields[field_index] = e;
field_index++;
add_entity(c, c->context.scope, name, e);
HashKey key = hash_string(name_token.string);
if (map_get(&entity_map, key) != NULL) {
// TODO(bill): Scope checking already checks the declaration
error(name_token, "`%.*s` is already declared in this type", LIT(name_token.string));
} else {
map_set(&entity_map, key, e);
fields[field_index++] = e;
add_entity(c, c->context.scope, name, e);
}
add_entity_use(&c->info, name, e);
}
add_entity_use(&c->info, name, e);
}
+17
View File
@@ -1483,6 +1483,23 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
case_ast_node(pa, PushAllocator, node);
Operand op = {};
check_expr(c, &op, pa->expr);
check_assignment(c, &op, t_allocator, make_string("argument to push_allocator"));
check_stmt(c, pa->body, mod_flags);
case_end;
case_ast_node(pa, PushContext, node);
Operand op = {};
check_expr(c, &op, pa->expr);
check_assignment(c, &op, t_context, make_string("argument to push_context"));
check_stmt(c, pa->body, mod_flags);
case_end;
+17 -13
View File
@@ -4,21 +4,20 @@ enum BasicKind {
Basic_Invalid,
Basic_bool,
Basic_i8,
Basic_i16,
Basic_i32,
Basic_i64,
Basic_u8,
Basic_i16,
Basic_u16,
Basic_i32,
Basic_u32,
Basic_i64,
Basic_u64,
Basic_f32,
Basic_f64,
Basic_int,
Basic_uint,
Basic_rawptr,
Basic_string,
Basic_any,
Basic_string, // ^u8 + int
Basic_any, // ^Type_Info + rawptr
Basic_UntypedBool,
Basic_UntypedInteger,
@@ -27,7 +26,6 @@ enum BasicKind {
Basic_UntypedString,
Basic_UntypedRune,
Basic_Count,
Basic_byte = Basic_u8,
@@ -294,12 +292,12 @@ gb_global Type basic_types[] = {
{0, Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}},
{0, Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
{0, Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
{0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
{0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
{0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
{0, Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
{0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
{0, Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
{0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
{0, Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
{0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
{0, Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
{0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
{0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
@@ -370,6 +368,12 @@ gb_global Type *t_type_info_raw_union = NULL;
gb_global Type *t_type_info_enum = NULL;
gb_global Type *t_type_info_any = NULL;
gb_global Type *t_allocator = NULL;
gb_global Type *t_allocator_ptr = NULL;
gb_global Type *t_context = NULL;
gb_global Type *t_context_ptr = NULL;
b32 is_type_named(Type *t) {
@@ -674,12 +678,12 @@ gb_global i64 basic_type_sizes[] = {
0, // Basic_Invalid
1, // Basic_bool
1, // Basic_i8
2, // Basic_i16
4, // Basic_i32
8, // Basic_i64
1, // Basic_u8
2, // Basic_i16
2, // Basic_u16
4, // Basic_i32
4, // Basic_u32
8, // Basic_i64
8, // Basic_u64
4, // Basic_f32
8, // Basic_f64
-1
View File
@@ -48,7 +48,6 @@ String ssa_mangle_name(ssaGen *s, String path, String name) {
if (str[i] == '\\') {
str[i] = '/';
}
}
char const *base = gb_path_base_name(str);
+10 -5
View File
@@ -84,8 +84,11 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
char hex_table[] = "0123456789ABCDEF";
isize buf_len = name.len + extra + 2;
u8 *buf = gb_alloc_array(gb_heap_allocator(), u8, buf_len);
defer (gb_free(gb_heap_allocator(), buf));
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
defer (gb_temp_arena_memory_end(tmp));
u8 *buf = gb_alloc_array(string_buffer_allocator, u8, buf_len);
isize j = 0;
@@ -809,9 +812,11 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
if (proc->module->generate_debug_info && proc->entity != NULL) {
ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity));
GB_ASSERT(di->kind == ssaDebugInfo_Proc);
ssa_fprintf(f, "!dbg !%d ", di->id);
if (proc->body != NULL) {
ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity));
GB_ASSERT(di->kind == ssaDebugInfo_Proc);
ssa_fprintf(f, "!dbg !%d ", di->id);
}
}
+45 -5
View File
@@ -2200,10 +2200,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *elem_size = ssa_make_const_int(allocator, s);
ssaValue *elem_align = ssa_make_const_int(allocator, a);
ssaValue *len = ssa_build_expr(proc, ce->args[1]);
ssaValue *len =ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[1]), t_int);
ssaValue *cap = len;
if (gb_array_count(ce->args) == 3) {
cap = ssa_build_expr(proc, ce->args[2]);
cap = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args[2]), t_int);
}
ssa_slice_bounds_check(proc, ast_node_token(ce->args[1]), v_zero, len, cap, false);
@@ -2218,9 +2218,13 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
ssaValue *ptr = ssa_emit_conv(proc, call, ptr_type, true);
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_zero32, ptr_type), ptr);
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_one32, t_int), len);
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), cap);
ssaValue *gep0 = ssa_emit_struct_gep(proc, slice, v_zero32, ptr_type);
ssaValue *gep1 = ssa_emit_struct_gep(proc, slice, v_one32, t_int);
ssaValue *gep2 = ssa_emit_struct_gep(proc, slice, v_two32, t_int);
ssa_emit_store(proc, gep0, ptr);
ssa_emit_store(proc, gep1, len);
ssa_emit_store(proc, gep2, cap);
return ssa_emit_load(proc, slice);
} break;
@@ -3678,6 +3682,42 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
ssa_emit_unreachable(proc);
case_end;
case_ast_node(pa, PushAllocator, node);
ssa_emit_comment(proc, make_string("PushAllocator"));
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
defer (ssa_emit_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
ssaValue *gep = ssa_emit_struct_gep(proc, context_ptr, 1, t_allocator_ptr);
ssa_emit_store(proc, gep, ssa_build_expr(proc, pa->expr));
proc->scope_index++;
ssa_build_stmt(proc, pa->body);
proc->scope_index--;
case_end;
case_ast_node(pa, PushContext, node);
ssa_emit_comment(proc, make_string("PushContext"));
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
defer (ssa_emit_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
ssa_emit_store(proc, context_ptr, ssa_build_expr(proc, pa->expr));
proc->scope_index++;
ssa_build_stmt(proc, pa->body);
proc->scope_index--;
case_end;
}
}
+41
View File
@@ -4,6 +4,47 @@
#include "string.cpp"
String get_module_dir(gbAllocator a) {
isize len = GetModuleFileNameW(NULL, NULL, 0);
if (len == 0) {
return make_string(NULL, 0);
}
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
defer (gb_temp_arena_memory_end(tmp));
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
String16 str = {text, len};
GetModuleFileNameW(NULL, text, len);
String path = string16_to_string(a, str);
for (isize i = path.len-1; i >= 0; i--) {
u8 c = path.text[i];
if (c == '/' || c == '\\') {
break;
}
path.len--;
}
return path;
}
String path_to_fullpath(gbAllocator a, String s) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
defer (gb_temp_arena_memory_end(tmp));
String16 string16 = string_to_string16(string_buffer_allocator, s);
DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
if (len == 0) {
return make_string(NULL, 0);
}
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
GetFullPathNameW(string16.text, len, text, NULL);
text[len] = 0;
return string16_to_string(a, make_string16(text, len));
}
struct BlockTimer {
u64 start;
+2 -2
View File
@@ -190,7 +190,7 @@ ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
}
failure:
compiler_error("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op.kind]));
ExactValue error_value = {};
return error_value;
@@ -212,7 +212,7 @@ i32 exact_value_order(ExactValue v) {
return 4;
default:
compiler_error("How'd you get here? Invalid Value.kind");
GB_PANIC("How'd you get here? Invalid Value.kind");
return -1;
}
}
+2 -2
View File
@@ -3948,7 +3948,7 @@ void const *gb_memrchr(void const *data, u8 c, isize n) {
gb_inline void *gb_alloc_align (gbAllocator a, isize size, isize alignment) { return a.proc(a.data, gbAllocation_Alloc, size, alignment, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void *gb_alloc (gbAllocator a, isize size) { return gb_alloc_align(a, size, GB_DEFAULT_MEMORY_ALIGNMENT); }
gb_inline void gb_free (gbAllocator a, void *ptr) { a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void gb_free (gbAllocator a, void *ptr) { if (ptr != NULL) a.proc(a.data, gbAllocation_Free, 0, 0, ptr, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void gb_free_all (gbAllocator a) { a.proc(a.data, gbAllocation_FreeAll, 0, 0, NULL, 0, GB_DEFAULT_ALLOCATOR_FLAGS); }
gb_inline void *gb_resize (gbAllocator a, void *ptr, isize old_size, isize new_size) { return gb_resize_align(a, ptr, old_size, new_size, GB_DEFAULT_MEMORY_ALIGNMENT); }
gb_inline void *gb_resize_align(gbAllocator a, void *ptr, isize old_size, isize new_size, isize alignment) { return a.proc(a.data, gbAllocation_Resize, new_size, alignment, ptr, old_size, GB_DEFAULT_ALLOCATOR_FLAGS); }
@@ -4698,7 +4698,7 @@ void gb_thread_set_name(gbThread *t, char const *name) {
tn.flags = 0;
__try {
RaiseException(0x406d1388, 0, gb_size_of(tn)/4, cast(usize *)&tn);
RaiseException(0x406d1388, 0, gb_size_of(tn)/4, cast(ULONG_PTR *)&tn);
} __except(1 /*EXCEPTION_EXECUTE_HANDLER*/) {
}
+72 -39
View File
@@ -7,26 +7,35 @@
#include "codegen/codegen.cpp"
i32 win32_exec_command_line_app(char *fmt, ...) {
STARTUPINFOA start_info = {gb_size_of(STARTUPINFOA)};
STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)};
PROCESS_INFORMATION pi = {};
char cmd_line[2048] = {};
isize cmd_len;
va_list va;
gbTempArenaMemory tmp;
String16 cmd;
start_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
start_info.wShowWindow = SW_SHOW;
start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
char cmd_line[2048] = {};
va_list va;
va_start(va, fmt);
gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
cmd_len = gb_snprintf_va(cmd_line, gb_size_of(cmd_line), fmt, va);
va_end(va);
if (CreateProcessA(NULL, cmd_line,
NULL, NULL, true, 0, NULL, NULL,
&start_info, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
defer (gb_temp_arena_memory_end(tmp));
cmd = string_to_string16(string_buffer_allocator, make_string(cast(u8 *)cmd_line, cmd_len-1));
if (CreateProcessW(NULL, cmd.text,
NULL, NULL, true, 0, NULL, NULL,
&start_info, &pi)) {
DWORD exit_code = 0;
WaitForSingleObject(pi.hProcess, INFINITE);
GetExitCodeProcess(pi.hProcess, &exit_code);
CloseHandle(pi.hProcess);
@@ -40,7 +49,7 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
}
}
// #define DISPLAY_TIMING
#define DISPLAY_TIMING
#if defined(DISPLAY_TIMING)
#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0
#define PRINT_TIMER(section) do { \
@@ -62,23 +71,50 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
#endif
int main(int argc, char **argv) {
if (argc < 2) {
gb_printf_err("Please specify a .odin file\n");
return 1;
}
char module_path_buf[300] = {};
String module_path = {};
module_path.text = cast(u8 *)module_path_buf;
module_path.len = GetModuleFileNameA(NULL, module_path_buf, gb_size_of(module_path_buf));
for (isize i = module_path.len-1; i >= 0; i--) {
u8 c = module_path.text[i];
if (c == '/' || c == '\\') {
break;
}
module_path.len--;
enum ArchKind {
ArchKind_x64,
ArchKind_x86,
};
struct ArchData {
BaseTypeSizes sizes;
String llc_flags;
String link_flags;
};
ArchData make_arch_data(ArchKind kind) {
ArchData data = {};
switch (kind) {
case ArchKind_x64:
default:
data.sizes.word_size = 8;
data.sizes.max_align = 16;
data.llc_flags = make_string("-march=x86-64 ");
data.link_flags = make_string("/machine:x64 /defaultlib:libcmt ");
break;
case ArchKind_x86:
data.sizes.word_size = 4;
data.sizes.max_align = 8;
data.llc_flags = make_string("-march=x86 ");
data.link_flags = make_string("/machine:x86 /defaultlib:libcmt ");
break;
}
return data;
}
int main(int argc, char **argv) {
if (argc < 2) {
gb_printf_err("using: %s [run] <filename> \n", argv[0]);
return 1;
}
init_string_buffer_memory();
String module_dir = get_module_dir(gb_heap_allocator());
// defer (gb_free(gb_heap_allocator(), module_dir.text));
INIT_TIMER();
@@ -104,16 +140,11 @@ int main(int argc, char **argv) {
PRINT_TIMER("Syntax Parser");
// print_ast(parser.files[0].decls, 0);
#if 1
Checker checker = {};
BaseTypeSizes sizes = {};
// NOTE(bill): x64
sizes.word_size = 8;
sizes.max_align = 16;
ArchData arch_data = make_arch_data(ArchKind_x64);
init_checker(&checker, &parser, sizes);
init_checker(&checker, &parser, arch_data.sizes);
// defer (destroy_checker(&checker));
check_parsed_files(&checker);
@@ -146,14 +177,14 @@ int main(int argc, char **argv) {
// For more passes arguments: http://llvm.org/docs/Passes.html
exit_code = win32_exec_command_line_app(
"%.*sbin/opt %s -o %.*s.bc "
"-memcpyopt "
"-mem2reg "
"-memcpyopt "
"-die -dse "
"-dce "
// "-S "
// "-debug-pass=Arguments "
"",
LIT(module_path),
LIT(module_dir),
output_name, LIT(output));
if (exit_code != 0) {
return exit_code;
@@ -164,10 +195,11 @@ int main(int argc, char **argv) {
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
exit_code = win32_exec_command_line_app(
"%.*sbin/llc %.*s.bc -filetype=obj -O0 "
"-march=x86-64 "
"%.*s "
"",
LIT(module_path),
LIT(output));
LIT(module_dir),
LIT(output),
LIT(arch_data.llc_flags));
if (exit_code != 0) {
return exit_code;
}
@@ -183,13 +215,14 @@ int main(int argc, char **argv) {
" %.*s.lib", LIT(lib));
lib_str = gb_string_appendc(lib_str, lib_str_buf);
}
char *linker_flags = "-nologo -DEFAULTLIB:libcmt -machine:x64 -incremental:no -opt:ref -subsystem:console";
char *linker_flags =
"/nologo /incremental:no /opt:ref /subsystem:console";
exit_code = win32_exec_command_line_app(
"link %.*s.obj -OUT:%.*s.exe %s %s "
"link %.*s.obj -OUT:%.*s.exe %s %.*s %s"
"",
LIT(output), LIT(output),
lib_str, linker_flags);
lib_str, LIT(arch_data.link_flags), linker_flags);
if (exit_code != 0) {
return exit_code;
}
+80 -46
View File
@@ -214,6 +214,16 @@ AST_NODE_KIND(_ComplexStmtBegin, "", struct{}) \
AstNode *clobber_list; \
isize output_count, input_count, clobber_count; \
}) \
AST_NODE_KIND(PushAllocator, "push_allocator statement", struct { \
Token token; \
AstNode *expr; \
AstNode *body; \
}) \
AST_NODE_KIND(PushContext, "push_context statement", struct { \
Token token; \
AstNode *expr; \
AstNode *body; \
}) \
\
AST_NODE_KIND(_ComplexStmtEnd, "", struct{}) \
AST_NODE_KIND(_StmtEnd, "", struct{}) \
@@ -414,6 +424,10 @@ Token ast_node_token(AstNode *node) {
return node->UsingStmt.token;
case AstNode_AsmStmt:
return node->AsmStmt.token;
case AstNode_PushAllocator:
return node->PushAllocator.token;
case AstNode_PushContext:
return node->PushContext.token;
case AstNode_BadDecl:
return node->BadDecl.begin;
case AstNode_VarDecl:
@@ -765,6 +779,21 @@ gb_inline AstNode *make_asm_stmt(AstFile *f, Token token, b32 is_volatile, Token
return result;
}
gb_inline AstNode *make_push_allocator(AstFile *f, Token token, AstNode *expr, AstNode *body) {
AstNode *result = make_node(f, AstNode_PushAllocator);
result->PushAllocator.token = token;
result->PushAllocator.expr = expr;
result->PushAllocator.body = body;
return result;
}
gb_inline AstNode *make_push_context(AstFile *f, Token token, AstNode *expr, AstNode *body) {
AstNode *result = make_node(f, AstNode_PushContext);
result->PushContext.token = token;
result->PushContext.expr = expr;
result->PushContext.body = body;
return result;
}
@@ -996,34 +1025,24 @@ void fix_advance_to_next_stmt(AstFile *f) {
}
b32 expect_semicolon_after_stmt(AstFile *f, AstNode *s) {
// if (s != NULL) {
// switch (s->kind) {
// case AstNode_ProcDecl:
// return true;
// case AstNode_TypeDecl: {
// switch (s->TypeDecl.type->kind) {
// case AstNode_StructType:
// case AstNode_UnionType:
// case AstNode_EnumType:
// case AstNode_ProcType:
// return true;
// }
// } break;
// }
// }
if (!allow_token(f, Token_Semicolon)) {
if (f->cursor[0].pos.line == f->cursor[-1].pos.line) {
if (f->cursor[0].kind != Token_CloseBrace) {
// CLEANUP(bill): Semicolon handling in parser
syntax_error(f->cursor[0],
"Expected `;` after %.*s, got `%.*s`",
LIT(ast_node_strings[s->kind]), LIT(token_strings[f->cursor[0].kind]));
return false;
}
}
if (allow_token(f, Token_Semicolon)) {
return true;
}
return true;
if (f->cursor[0].pos.line != f->cursor[-1].pos.line) {
return true;
}
switch (f->cursor[0].kind) {
case Token_EOF:
case Token_CloseBrace:
return true;
}
syntax_error(f->cursor[0],
"Expected `;` after %.*s, got `%.*s`",
LIT(ast_node_strings[s->kind]), LIT(token_strings[f->cursor[0].kind]));
return false;
}
@@ -2593,6 +2612,28 @@ AstNode *parse_stmt(AstFile *f) {
return make_using_stmt(f, token, node);
} break;
case Token_push_allocator: {
next_token(f);
isize prev_level = f->expr_level;
f->expr_level = -1;
AstNode *expr = parse_expr(f, false);
f->expr_level = prev_level;
AstNode *body = parse_block_stmt(f);
return make_push_allocator(f, token, expr, body);
} break;
case Token_push_context: {
next_token(f);
isize prev_level = f->expr_level;
f->expr_level = -1;
AstNode *expr = parse_expr(f, false);
f->expr_level = prev_level;
AstNode *body = parse_block_stmt(f);
return make_push_context(f, token, expr, body);
} break;
case Token_Hash: {
s = parse_tag_stmt(f, NULL);
String tag = s->TagStmt.name.string;
@@ -2706,10 +2747,8 @@ AstNodeArray parse_stmt_list(AstFile *f) {
}
ParseFileError init_ast_file(AstFile *f, String fullpath) {
if (!string_has_extension(fullpath, make_string("odin"))) {
// gb_printf_err("Only `.odin` files are allowed\n");
return ParseFile_WrongExtension;
}
TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
@@ -2809,34 +2848,29 @@ String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
gb_memcopy(str+i, base_dir.text, base_dir.len); i += base_dir.len;
gb_memcopy(str+i, path.text, path.len);
str[str_len] = '\0';
char *path_str = gb_path_get_full_name(a, cast(char *)str);
return make_string(path_str);
return path_to_fullpath(a, make_string(str, str_len));
}
String get_fullpath_core(gbAllocator a, String path) {
char buf[300] = {};
u32 buf_len = GetModuleFileNameA(GetModuleHandleA(NULL), buf, gb_size_of(buf));
for (isize i = buf_len-1; i >= 0; i--) {
if (buf[i] == '\\' ||
buf[i] == '/') {
break;
}
buf_len--;
}
String module_dir = get_module_dir(gb_heap_allocator());
defer (if (module_dir.len > 0) {
gb_free(gb_heap_allocator(), module_dir.text);
});
char core[] = "core/";
isize core_len = gb_size_of(core)-1;
isize str_len = buf_len + core_len + path.len;
isize str_len = module_dir.len + core_len + path.len;
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
defer (gb_free(gb_heap_allocator(), str));
gb_memcopy(str, buf, buf_len);
gb_memcopy(str+buf_len, core, core_len);
gb_memcopy(str+buf_len+core_len, path.text, path.len);
gb_memcopy(str, module_dir.text, module_dir.len);
gb_memcopy(str+module_dir.len, core, core_len);
gb_memcopy(str+module_dir.len+core_len, path.text, path.len);
str[str_len] = '\0';
char *path_str = gb_path_get_full_name(a, cast(char *)str);
return make_string(path_str);}
return path_to_fullpath(a, make_string(str, str_len));
}
// NOTE(bill): Returns true if it's added
b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
+91 -1
View File
@@ -1,13 +1,26 @@
gb_global gbArena string_buffer_arena = {};
gb_global gbAllocator string_buffer_allocator = {};
void init_string_buffer_memory() {
// NOTE(bill): This should be enough memory for file systems
gb_arena_init_from_allocator(&string_buffer_arena, gb_heap_allocator(), gb_megabytes(1));
string_buffer_allocator = gb_arena_allocator(&string_buffer_arena);
}
// NOTE(bill): Used for UTF-8 strings
typedef struct String {
u8 *text;
u8 * text;
isize len;
} String;
// NOTE(bill): used for printf style arguments
#define LIT(x) (x).len, (x).text
typedef struct String16 {
wchar_t *text;
isize len;
} String16;
gb_inline String make_string(u8 *text, isize len) {
@@ -20,6 +33,15 @@ gb_inline String make_string(u8 *text, isize len) {
return s;
}
gb_inline String16 make_string16(wchar_t *text, isize len) {
String16 s;
s.text = text;
s.len = len;
return s;
}
gb_inline String make_string(char *text) {
return make_string(cast(u8 *)cast(void *)text, gb_strlen(text));
}
@@ -133,6 +155,74 @@ b32 string_contains_char(String s, u8 c) {
return false;
}
// TODO(bill): Make this non-windows specific
String16 string_to_string16(gbAllocator a, String s) {
if (s.len < 1) {
return make_string16(NULL, 0);
}
int len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, NULL, 0);
if (len == 0) {
return make_string16(NULL, 0);
}
wchar_t *text = gb_alloc_array(a, wchar_t, len+1);
int len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
cast(char *)s.text, s.len, text, len);
if (len1 == 0) {
gb_free(a, text);
return make_string16(NULL, 0);
}
text[len] = 0;
return make_string16(text, len-1);
}
String string16_to_string(gbAllocator a, String16 s) {
if (s.len < 1) {
return make_string(NULL, 0);
}
int len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, NULL, 0,
NULL, NULL);
if (len == 0) {
return make_string(NULL, 0);
}
u8 *text = gb_alloc_array(a, u8, len+1);
int len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS,
s.text, s.len, cast(char *)text, len,
NULL, NULL);
if (len1 == 0) {
gb_free(a, text);
return make_string(NULL, 0);
}
text[len] = 0;
return make_string(text, len-1);
}
b32 unquote_char(String s, u8 quote, Rune *rune, b32 *multiple_bytes, String *tail_string) {
if (s.text[0] == quote &&
(quote == '$' || quote == '"')) {
+25 -23
View File
@@ -82,29 +82,31 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
\
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token_type, "type"), \
TOKEN_KIND(Token_proc, "proc"), \
TOKEN_KIND(Token_match, "match"), \
TOKEN_KIND(Token_break, "break"), \
TOKEN_KIND(Token_continue, "continue"), \
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
TOKEN_KIND(Token_case, "case"), \
TOKEN_KIND(Token_default, "default"), \
TOKEN_KIND(Token_then, "then"), \
TOKEN_KIND(Token_if, "if"), \
TOKEN_KIND(Token_else, "else"), \
TOKEN_KIND(Token_for, "for"), \
TOKEN_KIND(Token_range, "range"), \
TOKEN_KIND(Token_defer, "defer"), \
TOKEN_KIND(Token_return, "return"), \
TOKEN_KIND(Token_struct, "struct"), \
TOKEN_KIND(Token_union, "union"), \
TOKEN_KIND(Token_raw_union, "raw_union"), \
TOKEN_KIND(Token_enum, "enum"), \
TOKEN_KIND(Token_using, "using"), \
TOKEN_KIND(Token_asm, "asm"), \
TOKEN_KIND(Token_volatile, "volatile"), \
TOKEN_KIND(Token_atomic, "atomic"), \
TOKEN_KIND(Token_type, "type"), \
TOKEN_KIND(Token_proc, "proc"), \
TOKEN_KIND(Token_match, "match"), \
TOKEN_KIND(Token_break, "break"), \
TOKEN_KIND(Token_continue, "continue"), \
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
TOKEN_KIND(Token_case, "case"), \
TOKEN_KIND(Token_default, "default"), \
TOKEN_KIND(Token_then, "then"), \
TOKEN_KIND(Token_if, "if"), \
TOKEN_KIND(Token_else, "else"), \
TOKEN_KIND(Token_for, "for"), \
TOKEN_KIND(Token_range, "range"), \
TOKEN_KIND(Token_defer, "defer"), \
TOKEN_KIND(Token_return, "return"), \
TOKEN_KIND(Token_struct, "struct"), \
TOKEN_KIND(Token_union, "union"), \
TOKEN_KIND(Token_raw_union, "raw_union"), \
TOKEN_KIND(Token_enum, "enum"), \
TOKEN_KIND(Token_using, "using"), \
TOKEN_KIND(Token_asm, "asm"), \
TOKEN_KIND(Token_volatile, "volatile"), \
TOKEN_KIND(Token_atomic, "atomic"), \
TOKEN_KIND(Token_push_allocator, "push_allocator"), \
TOKEN_KIND(Token_push_context, "push_context"), \
TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
TOKEN_KIND(Token_Count, "")