mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Unicode file loading; push_allocator & push_context
This commit is contained in:
@@ -24,7 +24,7 @@ set compiler_warnings= ^
|
|||||||
-wd4505 -wd4512 -wd4550
|
-wd4505 -wd4512 -wd4550
|
||||||
|
|
||||||
set compiler_includes=
|
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
|
set linker_flags= -incremental:no -opt:ref -subsystem:console
|
||||||
|
|
||||||
|
|||||||
+14
-2
@@ -1,19 +1,31 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin"
|
||||||
#import "os.odin"
|
#import "os.odin"
|
||||||
|
#import "mem.odin"
|
||||||
// #import "http_test.odin" as ht
|
// #import "http_test.odin" as ht
|
||||||
// #import "game.odin" as game
|
// #import "game.odin" as game
|
||||||
// #import "punity.odin" as pn
|
// #import "punity.odin" as pn
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
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()
|
// struct_padding()
|
||||||
// bounds_checking()
|
// bounds_checking()
|
||||||
// type_introspection()
|
// type_introspection()
|
||||||
// any_type()
|
// any_type()
|
||||||
// crazy_introspection()
|
// crazy_introspection()
|
||||||
namespaces_and_files()
|
// namespaces_and_files()
|
||||||
// miscellany()
|
// miscellany()
|
||||||
|
|
||||||
// ht.run()
|
// ht.run()
|
||||||
// game.run()
|
// game.run()
|
||||||
// {
|
// {
|
||||||
|
|||||||
@@ -33,4 +33,3 @@ thing :: proc() {
|
|||||||
thing :: proc() {
|
thing :: proc() {
|
||||||
println("Hello5!")
|
println("Hello5!")
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -130,6 +130,7 @@ memory_compare :: proc(dst, src: rawptr, len: int) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
memory_copy :: proc(dst, src: rawptr, len: int) #inline {
|
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 :: 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)
|
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 {
|
Mode :: enum {
|
||||||
ALLOC,
|
ALLOC,
|
||||||
FREE,
|
FREE,
|
||||||
@@ -159,7 +160,7 @@ Allocator :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Context :: struct {
|
Context :: struct #ordered {
|
||||||
thread_id: int
|
thread_id: int
|
||||||
|
|
||||||
allocator: Allocator
|
allocator: Allocator
|
||||||
@@ -279,8 +280,6 @@ __default_allocator :: proc() -> Allocator {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__string_eq :: proc(a, b: string) -> bool {
|
__string_eq :: proc(a, b: string) -> bool {
|
||||||
if a.count != b.count {
|
if a.count != b.count {
|
||||||
return false
|
return false
|
||||||
@@ -382,3 +381,5 @@ __enum_to_string :: proc(info: ^Type_Info, value: i64) -> string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
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
|
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
||||||
set _NO_DEBUG_HEAP=1
|
set _NO_DEBUG_HEAP=1
|
||||||
|
|
||||||
|
|||||||
+22
-4
@@ -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) {
|
if (t_type_info == NULL) {
|
||||||
String type_info_str = make_string("Type_Info");
|
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
||||||
Entity *e = current_scope_lookup_entity(c->global_scope, type_info_str);
|
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
compiler_error("Could not find type declaration for `Type_Info`\n"
|
compiler_error("Could not find type declaration for `Type_Info`\n"
|
||||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
"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;
|
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);
|
check_global_entity(c, Entity_TypeName);
|
||||||
|
|
||||||
init_type_info_types(c);
|
init_runtime_types(c);
|
||||||
#if 1
|
#if 1
|
||||||
check_global_entity(c, Entity_Constant);
|
check_global_entity(c, Entity_Constant);
|
||||||
check_global_entity(c, Entity_Procedure);
|
check_global_entity(c, Entity_Procedure);
|
||||||
|
|||||||
+39
-23
@@ -266,15 +266,19 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
AstNode *name = cd->names[i];
|
AstNode *name = cd->names[i];
|
||||||
Entity *e = entities[i];
|
Entity *e = entities[i];
|
||||||
Token name_token = name->Ident;
|
Token name_token = name->Ident;
|
||||||
HashKey key = hash_string(name_token.string);
|
if (name_token.string == make_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;
|
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) {
|
} else if (decl->kind == AstNode_TypeDecl) {
|
||||||
ast_node(td, TypeDecl, decl);
|
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);
|
add_entity(c, c->context.scope, td->name, e);
|
||||||
check_type_decl(c, e, td->type, NULL, NULL);
|
check_type_decl(c, e, td->type, NULL, NULL);
|
||||||
|
|
||||||
HashKey key = hash_string(name_token.string);
|
if (name_token.string == make_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;
|
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;
|
type->Named.type_name = e;
|
||||||
add_entity(c, c->context.scope, 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);
|
HashKey key = hash_string(name_token.string);
|
||||||
if (map_get(&entity_map, key) != NULL) {
|
if (map_get(&entity_map, key) != NULL) {
|
||||||
// TODO(bill): Scope checking already checks the declaration
|
// 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;
|
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);
|
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 (name_token.string == make_string("_")) {
|
||||||
if (map_get(&entity_map, key) != NULL) {
|
fields[field_index++] = e;
|
||||||
// TODO(bill): Scope checking already checks the declaration
|
|
||||||
error(name_token, "`%.*s` is already declared in this type", LIT(name_token.string));
|
|
||||||
} else {
|
} else {
|
||||||
map_set(&entity_map, key, e);
|
HashKey key = hash_string(name_token.string);
|
||||||
fields[field_index] = e;
|
if (map_get(&entity_map, key) != NULL) {
|
||||||
field_index++;
|
// TODO(bill): Scope checking already checks the declaration
|
||||||
add_entity(c, c->context.scope, name, e);
|
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -4,21 +4,20 @@ enum BasicKind {
|
|||||||
Basic_Invalid,
|
Basic_Invalid,
|
||||||
Basic_bool,
|
Basic_bool,
|
||||||
Basic_i8,
|
Basic_i8,
|
||||||
Basic_i16,
|
|
||||||
Basic_i32,
|
|
||||||
Basic_i64,
|
|
||||||
Basic_u8,
|
Basic_u8,
|
||||||
|
Basic_i16,
|
||||||
Basic_u16,
|
Basic_u16,
|
||||||
|
Basic_i32,
|
||||||
Basic_u32,
|
Basic_u32,
|
||||||
|
Basic_i64,
|
||||||
Basic_u64,
|
Basic_u64,
|
||||||
Basic_f32,
|
Basic_f32,
|
||||||
Basic_f64,
|
Basic_f64,
|
||||||
Basic_int,
|
Basic_int,
|
||||||
Basic_uint,
|
Basic_uint,
|
||||||
Basic_rawptr,
|
Basic_rawptr,
|
||||||
Basic_string,
|
Basic_string, // ^u8 + int
|
||||||
|
Basic_any, // ^Type_Info + rawptr
|
||||||
Basic_any,
|
|
||||||
|
|
||||||
Basic_UntypedBool,
|
Basic_UntypedBool,
|
||||||
Basic_UntypedInteger,
|
Basic_UntypedInteger,
|
||||||
@@ -27,7 +26,6 @@ enum BasicKind {
|
|||||||
Basic_UntypedString,
|
Basic_UntypedString,
|
||||||
Basic_UntypedRune,
|
Basic_UntypedRune,
|
||||||
|
|
||||||
|
|
||||||
Basic_Count,
|
Basic_Count,
|
||||||
|
|
||||||
Basic_byte = Basic_u8,
|
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_Invalid, 0, STR_LIT("invalid type")}},
|
||||||
{0, Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
{0, Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
||||||
{0, Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
|
{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_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_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_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_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
||||||
{0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
{0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
||||||
{0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
{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_enum = NULL;
|
||||||
gb_global Type *t_type_info_any = 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) {
|
b32 is_type_named(Type *t) {
|
||||||
@@ -674,12 +678,12 @@ gb_global i64 basic_type_sizes[] = {
|
|||||||
0, // Basic_Invalid
|
0, // Basic_Invalid
|
||||||
1, // Basic_bool
|
1, // Basic_bool
|
||||||
1, // Basic_i8
|
1, // Basic_i8
|
||||||
2, // Basic_i16
|
|
||||||
4, // Basic_i32
|
|
||||||
8, // Basic_i64
|
|
||||||
1, // Basic_u8
|
1, // Basic_u8
|
||||||
|
2, // Basic_i16
|
||||||
2, // Basic_u16
|
2, // Basic_u16
|
||||||
|
4, // Basic_i32
|
||||||
4, // Basic_u32
|
4, // Basic_u32
|
||||||
|
8, // Basic_i64
|
||||||
8, // Basic_u64
|
8, // Basic_u64
|
||||||
4, // Basic_f32
|
4, // Basic_f32
|
||||||
8, // Basic_f64
|
8, // Basic_f64
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ String ssa_mangle_name(ssaGen *s, String path, String name) {
|
|||||||
if (str[i] == '\\') {
|
if (str[i] == '\\') {
|
||||||
str[i] = '/';
|
str[i] = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *base = gb_path_base_name(str);
|
char const *base = gb_path_base_name(str);
|
||||||
|
|||||||
@@ -84,8 +84,11 @@ void ssa_print_escape_string(ssaFileBuffer *f, String name, b32 print_quotes) {
|
|||||||
|
|
||||||
char hex_table[] = "0123456789ABCDEF";
|
char hex_table[] = "0123456789ABCDEF";
|
||||||
isize buf_len = name.len + extra + 2;
|
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;
|
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) {
|
if (proc->module->generate_debug_info && proc->entity != NULL) {
|
||||||
ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
if (proc->body != NULL) {
|
||||||
GB_ASSERT(di->kind == ssaDebugInfo_Proc);
|
ssaDebugInfo *di = *map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
||||||
ssa_fprintf(f, "!dbg !%d ", di->id);
|
GB_ASSERT(di->kind == ssaDebugInfo_Proc);
|
||||||
|
ssa_fprintf(f, "!dbg !%d ", di->id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+45
-5
@@ -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_size = ssa_make_const_int(allocator, s);
|
||||||
ssaValue *elem_align = ssa_make_const_int(allocator, a);
|
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;
|
ssaValue *cap = len;
|
||||||
if (gb_array_count(ce->args) == 3) {
|
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);
|
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 *ptr = ssa_emit_conv(proc, call, ptr_type, true);
|
||||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
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);
|
ssaValue *gep0 = ssa_emit_struct_gep(proc, slice, v_zero32, ptr_type);
|
||||||
ssa_emit_store(proc, ssa_emit_struct_gep(proc, slice, v_two32, t_int), cap);
|
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);
|
return ssa_emit_load(proc, slice);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -3678,6 +3682,42 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|||||||
ssa_emit_unreachable(proc);
|
ssa_emit_unreachable(proc);
|
||||||
case_end;
|
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;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,47 @@
|
|||||||
|
|
||||||
#include "string.cpp"
|
#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 {
|
struct BlockTimer {
|
||||||
u64 start;
|
u64 start;
|
||||||
|
|||||||
+2
-2
@@ -190,7 +190,7 @@ ExactValue exact_unary_operator_value(Token op, ExactValue v, i32 precision) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
failure:
|
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 = {};
|
ExactValue error_value = {};
|
||||||
return error_value;
|
return error_value;
|
||||||
@@ -212,7 +212,7 @@ i32 exact_value_order(ExactValue v) {
|
|||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
compiler_error("How'd you get here? Invalid Value.kind");
|
GB_PANIC("How'd you get here? Invalid Value.kind");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -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_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_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_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 (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); }
|
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;
|
tn.flags = 0;
|
||||||
|
|
||||||
__try {
|
__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*/) {
|
} __except(1 /*EXCEPTION_EXECUTE_HANDLER*/) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+72
-39
@@ -7,26 +7,35 @@
|
|||||||
#include "codegen/codegen.cpp"
|
#include "codegen/codegen.cpp"
|
||||||
|
|
||||||
i32 win32_exec_command_line_app(char *fmt, ...) {
|
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 = {};
|
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.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||||
start_info.wShowWindow = SW_SHOW;
|
start_info.wShowWindow = SW_SHOW;
|
||||||
start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
char cmd_line[2048] = {};
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
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);
|
va_end(va);
|
||||||
|
|
||||||
if (CreateProcessA(NULL, cmd_line,
|
tmp = gb_temp_arena_memory_begin(&string_buffer_arena);
|
||||||
NULL, NULL, true, 0, NULL, NULL,
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
&start_info, &pi)) {
|
|
||||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
||||||
|
|
||||||
|
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;
|
DWORD exit_code = 0;
|
||||||
|
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||||
|
|
||||||
CloseHandle(pi.hProcess);
|
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)
|
#if defined(DISPLAY_TIMING)
|
||||||
#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0
|
#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0
|
||||||
#define PRINT_TIMER(section) do { \
|
#define PRINT_TIMER(section) do { \
|
||||||
@@ -62,23 +71,50 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
enum ArchKind {
|
||||||
if (argc < 2) {
|
ArchKind_x64,
|
||||||
gb_printf_err("Please specify a .odin file\n");
|
ArchKind_x86,
|
||||||
return 1;
|
};
|
||||||
}
|
|
||||||
char module_path_buf[300] = {};
|
struct ArchData {
|
||||||
String module_path = {};
|
BaseTypeSizes sizes;
|
||||||
module_path.text = cast(u8 *)module_path_buf;
|
String llc_flags;
|
||||||
module_path.len = GetModuleFileNameA(NULL, module_path_buf, gb_size_of(module_path_buf));
|
String link_flags;
|
||||||
for (isize i = module_path.len-1; i >= 0; i--) {
|
};
|
||||||
u8 c = module_path.text[i];
|
|
||||||
if (c == '/' || c == '\\') {
|
ArchData make_arch_data(ArchKind kind) {
|
||||||
break;
|
ArchData data = {};
|
||||||
}
|
|
||||||
module_path.len--;
|
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();
|
INIT_TIMER();
|
||||||
|
|
||||||
@@ -104,16 +140,11 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
PRINT_TIMER("Syntax Parser");
|
PRINT_TIMER("Syntax Parser");
|
||||||
|
|
||||||
// print_ast(parser.files[0].decls, 0);
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
Checker checker = {};
|
Checker checker = {};
|
||||||
BaseTypeSizes sizes = {};
|
ArchData arch_data = make_arch_data(ArchKind_x64);
|
||||||
// NOTE(bill): x64
|
|
||||||
sizes.word_size = 8;
|
|
||||||
sizes.max_align = 16;
|
|
||||||
|
|
||||||
init_checker(&checker, &parser, sizes);
|
init_checker(&checker, &parser, arch_data.sizes);
|
||||||
// defer (destroy_checker(&checker));
|
// defer (destroy_checker(&checker));
|
||||||
|
|
||||||
check_parsed_files(&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
|
// For more passes arguments: http://llvm.org/docs/Passes.html
|
||||||
exit_code = win32_exec_command_line_app(
|
exit_code = win32_exec_command_line_app(
|
||||||
"%.*sbin/opt %s -o %.*s.bc "
|
"%.*sbin/opt %s -o %.*s.bc "
|
||||||
"-memcpyopt "
|
|
||||||
"-mem2reg "
|
"-mem2reg "
|
||||||
|
"-memcpyopt "
|
||||||
"-die -dse "
|
"-die -dse "
|
||||||
"-dce "
|
"-dce "
|
||||||
// "-S "
|
// "-S "
|
||||||
// "-debug-pass=Arguments "
|
// "-debug-pass=Arguments "
|
||||||
"",
|
"",
|
||||||
LIT(module_path),
|
LIT(module_dir),
|
||||||
output_name, LIT(output));
|
output_name, LIT(output));
|
||||||
if (exit_code != 0) {
|
if (exit_code != 0) {
|
||||||
return exit_code;
|
return exit_code;
|
||||||
@@ -164,10 +195,11 @@ int main(int argc, char **argv) {
|
|||||||
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
|
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
|
||||||
exit_code = win32_exec_command_line_app(
|
exit_code = win32_exec_command_line_app(
|
||||||
"%.*sbin/llc %.*s.bc -filetype=obj -O0 "
|
"%.*sbin/llc %.*s.bc -filetype=obj -O0 "
|
||||||
"-march=x86-64 "
|
"%.*s "
|
||||||
"",
|
"",
|
||||||
LIT(module_path),
|
LIT(module_dir),
|
||||||
LIT(output));
|
LIT(output),
|
||||||
|
LIT(arch_data.llc_flags));
|
||||||
if (exit_code != 0) {
|
if (exit_code != 0) {
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
@@ -183,13 +215,14 @@ int main(int argc, char **argv) {
|
|||||||
" %.*s.lib", LIT(lib));
|
" %.*s.lib", LIT(lib));
|
||||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
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(
|
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),
|
LIT(output), LIT(output),
|
||||||
lib_str, linker_flags);
|
lib_str, LIT(arch_data.link_flags), linker_flags);
|
||||||
if (exit_code != 0) {
|
if (exit_code != 0) {
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|||||||
+80
-46
@@ -214,6 +214,16 @@ AST_NODE_KIND(_ComplexStmtBegin, "", struct{}) \
|
|||||||
AstNode *clobber_list; \
|
AstNode *clobber_list; \
|
||||||
isize output_count, input_count, clobber_count; \
|
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(_ComplexStmtEnd, "", struct{}) \
|
||||||
AST_NODE_KIND(_StmtEnd, "", struct{}) \
|
AST_NODE_KIND(_StmtEnd, "", struct{}) \
|
||||||
@@ -414,6 +424,10 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return node->UsingStmt.token;
|
return node->UsingStmt.token;
|
||||||
case AstNode_AsmStmt:
|
case AstNode_AsmStmt:
|
||||||
return node->AsmStmt.token;
|
return node->AsmStmt.token;
|
||||||
|
case AstNode_PushAllocator:
|
||||||
|
return node->PushAllocator.token;
|
||||||
|
case AstNode_PushContext:
|
||||||
|
return node->PushContext.token;
|
||||||
case AstNode_BadDecl:
|
case AstNode_BadDecl:
|
||||||
return node->BadDecl.begin;
|
return node->BadDecl.begin;
|
||||||
case AstNode_VarDecl:
|
case AstNode_VarDecl:
|
||||||
@@ -765,6 +779,21 @@ gb_inline AstNode *make_asm_stmt(AstFile *f, Token token, b32 is_volatile, Token
|
|||||||
return result;
|
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) {
|
b32 expect_semicolon_after_stmt(AstFile *f, AstNode *s) {
|
||||||
// if (s != NULL) {
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
// switch (s->kind) {
|
return true;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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);
|
return make_using_stmt(f, token, node);
|
||||||
} break;
|
} 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: {
|
case Token_Hash: {
|
||||||
s = parse_tag_stmt(f, NULL);
|
s = parse_tag_stmt(f, NULL);
|
||||||
String tag = s->TagStmt.name.string;
|
String tag = s->TagStmt.name.string;
|
||||||
@@ -2706,10 +2747,8 @@ AstNodeArray parse_stmt_list(AstFile *f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ParseFileError init_ast_file(AstFile *f, String fullpath) {
|
ParseFileError init_ast_file(AstFile *f, String fullpath) {
|
||||||
if (!string_has_extension(fullpath, make_string("odin"))) {
|
if (!string_has_extension(fullpath, make_string("odin"))) {
|
||||||
// gb_printf_err("Only `.odin` files are allowed\n");
|
|
||||||
return ParseFile_WrongExtension;
|
return ParseFile_WrongExtension;
|
||||||
}
|
}
|
||||||
TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
|
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, base_dir.text, base_dir.len); i += base_dir.len;
|
||||||
gb_memcopy(str+i, path.text, path.len);
|
gb_memcopy(str+i, path.text, path.len);
|
||||||
str[str_len] = '\0';
|
str[str_len] = '\0';
|
||||||
char *path_str = gb_path_get_full_name(a, cast(char *)str);
|
return path_to_fullpath(a, make_string(str, str_len));
|
||||||
return make_string(path_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String get_fullpath_core(gbAllocator a, String path) {
|
String get_fullpath_core(gbAllocator a, String path) {
|
||||||
char buf[300] = {};
|
String module_dir = get_module_dir(gb_heap_allocator());
|
||||||
u32 buf_len = GetModuleFileNameA(GetModuleHandleA(NULL), buf, gb_size_of(buf));
|
defer (if (module_dir.len > 0) {
|
||||||
for (isize i = buf_len-1; i >= 0; i--) {
|
gb_free(gb_heap_allocator(), module_dir.text);
|
||||||
if (buf[i] == '\\' ||
|
});
|
||||||
buf[i] == '/') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
buf_len--;
|
|
||||||
}
|
|
||||||
|
|
||||||
char core[] = "core/";
|
char core[] = "core/";
|
||||||
isize core_len = gb_size_of(core)-1;
|
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);
|
u8 *str = gb_alloc_array(gb_heap_allocator(), u8, str_len+1);
|
||||||
defer (gb_free(gb_heap_allocator(), str));
|
defer (gb_free(gb_heap_allocator(), str));
|
||||||
|
|
||||||
gb_memcopy(str, buf, buf_len);
|
gb_memcopy(str, module_dir.text, module_dir.len);
|
||||||
gb_memcopy(str+buf_len, core, core_len);
|
gb_memcopy(str+module_dir.len, core, core_len);
|
||||||
gb_memcopy(str+buf_len+core_len, path.text, path.len);
|
gb_memcopy(str+module_dir.len+core_len, path.text, path.len);
|
||||||
str[str_len] = '\0';
|
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
|
// NOTE(bill): Returns true if it's added
|
||||||
b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
|
b32 try_add_foreign_system_library_path(Parser *p, String import_file) {
|
||||||
|
|||||||
+91
-1
@@ -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
|
// NOTE(bill): Used for UTF-8 strings
|
||||||
typedef struct String {
|
typedef struct String {
|
||||||
u8 *text;
|
u8 * text;
|
||||||
isize len;
|
isize len;
|
||||||
} String;
|
} String;
|
||||||
// NOTE(bill): used for printf style arguments
|
// NOTE(bill): used for printf style arguments
|
||||||
#define LIT(x) (x).len, (x).text
|
#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) {
|
gb_inline String make_string(u8 *text, isize len) {
|
||||||
@@ -20,6 +33,15 @@ gb_inline String make_string(u8 *text, isize len) {
|
|||||||
return s;
|
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) {
|
gb_inline String make_string(char *text) {
|
||||||
return make_string(cast(u8 *)cast(void *)text, gb_strlen(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;
|
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) {
|
b32 unquote_char(String s, u8 quote, Rune *rune, b32 *multiple_bytes, String *tail_string) {
|
||||||
if (s.text[0] == quote &&
|
if (s.text[0] == quote &&
|
||||||
(quote == '$' || quote == '"')) {
|
(quote == '$' || quote == '"')) {
|
||||||
|
|||||||
+25
-23
@@ -82,29 +82,31 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
|
|||||||
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||||
\
|
\
|
||||||
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||||
TOKEN_KIND(Token_type, "type"), \
|
TOKEN_KIND(Token_type, "type"), \
|
||||||
TOKEN_KIND(Token_proc, "proc"), \
|
TOKEN_KIND(Token_proc, "proc"), \
|
||||||
TOKEN_KIND(Token_match, "match"), \
|
TOKEN_KIND(Token_match, "match"), \
|
||||||
TOKEN_KIND(Token_break, "break"), \
|
TOKEN_KIND(Token_break, "break"), \
|
||||||
TOKEN_KIND(Token_continue, "continue"), \
|
TOKEN_KIND(Token_continue, "continue"), \
|
||||||
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
|
TOKEN_KIND(Token_fallthrough, "fallthrough"), \
|
||||||
TOKEN_KIND(Token_case, "case"), \
|
TOKEN_KIND(Token_case, "case"), \
|
||||||
TOKEN_KIND(Token_default, "default"), \
|
TOKEN_KIND(Token_default, "default"), \
|
||||||
TOKEN_KIND(Token_then, "then"), \
|
TOKEN_KIND(Token_then, "then"), \
|
||||||
TOKEN_KIND(Token_if, "if"), \
|
TOKEN_KIND(Token_if, "if"), \
|
||||||
TOKEN_KIND(Token_else, "else"), \
|
TOKEN_KIND(Token_else, "else"), \
|
||||||
TOKEN_KIND(Token_for, "for"), \
|
TOKEN_KIND(Token_for, "for"), \
|
||||||
TOKEN_KIND(Token_range, "range"), \
|
TOKEN_KIND(Token_range, "range"), \
|
||||||
TOKEN_KIND(Token_defer, "defer"), \
|
TOKEN_KIND(Token_defer, "defer"), \
|
||||||
TOKEN_KIND(Token_return, "return"), \
|
TOKEN_KIND(Token_return, "return"), \
|
||||||
TOKEN_KIND(Token_struct, "struct"), \
|
TOKEN_KIND(Token_struct, "struct"), \
|
||||||
TOKEN_KIND(Token_union, "union"), \
|
TOKEN_KIND(Token_union, "union"), \
|
||||||
TOKEN_KIND(Token_raw_union, "raw_union"), \
|
TOKEN_KIND(Token_raw_union, "raw_union"), \
|
||||||
TOKEN_KIND(Token_enum, "enum"), \
|
TOKEN_KIND(Token_enum, "enum"), \
|
||||||
TOKEN_KIND(Token_using, "using"), \
|
TOKEN_KIND(Token_using, "using"), \
|
||||||
TOKEN_KIND(Token_asm, "asm"), \
|
TOKEN_KIND(Token_asm, "asm"), \
|
||||||
TOKEN_KIND(Token_volatile, "volatile"), \
|
TOKEN_KIND(Token_volatile, "volatile"), \
|
||||||
TOKEN_KIND(Token_atomic, "atomic"), \
|
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__KeywordEnd, "_KeywordEnd"), \
|
||||||
TOKEN_KIND(Token_Count, "")
|
TOKEN_KIND(Token_Count, "")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user