Merge branch 'master' of github.com:gingerBill/Odin

This commit is contained in:
Mikkel Hjortshoej
2017-06-11 19:47:05 +02:00
28 changed files with 2645 additions and 2286 deletions
+6 -9
View File
@@ -4,8 +4,8 @@
set exe_name=odin.exe
:: Debug = 0, Release = 1
set release_mode=1
set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
set release_mode=0
set compiler_flags= -nologo -Oi -TP -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
if %release_mode% EQU 0 ( rem Debug
set compiler_flags=%compiler_flags% -Od -MDd -Z7
@@ -42,13 +42,10 @@ set linker_settings=%libs% %linker_flags%
del *.pdb > NUL 2> NUL
del *.ilk > NUL 2> NUL
odin run code/demo.odin
rem cl %compiler_settings% "src\main.c" ^
rem /link %linker_settings% -OUT:%exe_name% ^
rem && odin run code/demo.odin
rem && odin build code/metagen.odin ^
rem && call "code\metagen.exe" "src\ast_nodes.metagen"
rem && odin run code/Jaze/src/main.odin
rem odin run code/demo.odin
cl %compiler_settings% "src\main.cpp" ^
/link %linker_settings% -OUT:%exe_name% ^
&& odin run code/demo.odin
del *.obj > NUL 2> NUL
+94 -94
View File
@@ -1,98 +1,7 @@
#define ARRAY_GROW_FORMULA(x) (2*(x) + 8)
GB_STATIC_ASSERT(ARRAY_GROW_FORMULA(0) > 0);
#define Array(Type_) struct { \
gbAllocator allocator; \
Type_ * e; \
isize count; \
isize capacity; \
}
typedef Array(void) ArrayVoid;
#define array_init_reserve(x_, allocator_, init_capacity_) do { \
void **e = cast(void **)&((x_)->e); \
GB_ASSERT((x_) != NULL); \
(x_)->allocator = (allocator_); \
(x_)->count = 0; \
(x_)->capacity = (init_capacity_); \
*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_capacity_)); \
} while (0)
#define array_init_count(x_, allocator_, init_count_) do { \
void **e = cast(void **)&((x_)->e); \
GB_ASSERT((x_) != NULL); \
(x_)->allocator = (allocator_); \
(x_)->count = (init_count_); \
(x_)->capacity = (init_count_); \
*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_count_)); \
} while (0)
#define array_init(x_, allocator_) do { array_init_reserve(x_, allocator_, ARRAY_GROW_FORMULA(0)); } while (0)
#define array_free(x_) do { gb_free((x_)->allocator, (x_)->e); } while (0)
#define array_set_capacity(x_, capacity_) do { array__set_capacity((x_), (capacity_), gb_size_of(*(x_)->e)); } while (0)
#define array_grow(x_, min_capacity_) do { \
isize new_capacity = ARRAY_GROW_FORMULA((x_)->capacity); \
if (new_capacity < (min_capacity_)) { \
new_capacity = (min_capacity_); \
} \
array_set_capacity(x_, new_capacity); \
} while (0)
#define array_add(x_, item_) do { \
if ((x_)->capacity < (x_)->count+1) { \
array_grow(x_, 0); \
} \
(x_)->e[(x_)->count++] = item_; \
} while (0)
#define array_pop(x_) do { GB_ASSERT((x_)->count > 0); (x_)->count--; } while (0)
#define array_clear(x_) do { (x_)->count = 0; } while (0)
#define array_resize(x_, new_count_) do { \
if ((x_)->capacity < (new_count_)) { \
array_grow((x_), (new_count_)); \
} \
(x_)->count = (new_count_); \
} while (0)
#define array_reserve(x_, new_capacity_) do { \
if ((x_)->capacity < (new_capacity_)) { \
array_set_capacity((x_), (new_capacity_)); \
} \
} while (0)
void array__set_capacity(void *ptr, isize capacity, isize element_size) {
ArrayVoid *x = cast(ArrayVoid *)ptr;
GB_ASSERT(ptr != NULL);
GB_ASSERT(element_size > 0);
if (capacity == x->capacity) {
return;
}
if (capacity < x->count) {
if (x->capacity < capacity) {
isize new_capacity = ARRAY_GROW_FORMULA(x->capacity);
if (new_capacity < capacity) {
new_capacity = capacity;
}
array__set_capacity(ptr, new_capacity, element_size);
}
x->count = capacity;
}
x->e = gb_resize(x->allocator, x->e, element_size*x->capacity, element_size*capacity);
x->capacity = capacity;
}
#if 0
#if 1
template <typename T>
struct Array {
gbAllocator allocator;
@@ -224,6 +133,97 @@ void array_set_capacity(Array<T> *array, isize capacity) {
array->capacity = capacity;
}
#endif
#if 0
#define Array(Type_) struct { \
gbAllocator allocator; \
Type_ * e; \
isize count; \
isize capacity; \
}
typedef Array(void) ArrayVoid;
#define array_init_reserve(x_, allocator_, init_capacity_) do { \
void **e = cast(void **)&((x_)->e); \
GB_ASSERT((x_) != NULL); \
(x_)->allocator = (allocator_); \
(x_)->count = 0; \
(x_)->capacity = (init_capacity_); \
*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_capacity_)); \
} while (0)
#define array_init_count(x_, allocator_, init_count_) do { \
void **e = cast(void **)&((x_)->e); \
GB_ASSERT((x_) != NULL); \
(x_)->allocator = (allocator_); \
(x_)->count = (init_count_); \
(x_)->capacity = (init_count_); \
*e = gb_alloc((allocator_), gb_size_of(*(x_)->e)*(init_count_)); \
} while (0)
#define array_init(x_, allocator_) do { array_init_reserve(x_, allocator_, ARRAY_GROW_FORMULA(0)); } while (0)
#define array_free(x_) do { gb_free((x_)->allocator, (x_)->e); } while (0)
#define array_set_capacity(x_, capacity_) do { array__set_capacity((x_), (capacity_), gb_size_of(*(x_)->e)); } while (0)
#define array_grow(x_, min_capacity_) do { \
isize new_capacity = ARRAY_GROW_FORMULA((x_)->capacity); \
if (new_capacity < (min_capacity_)) { \
new_capacity = (min_capacity_); \
} \
array_set_capacity(x_, new_capacity); \
} while (0)
#define array_add(x_, item_) do { \
if ((x_)->capacity < (x_)->count+1) { \
array_grow(x_, 0); \
} \
(x_)->e[(x_)->count++] = item_; \
} while (0)
#define array_pop(x_) do { GB_ASSERT((x_)->count > 0); (x_)->count--; } while (0)
#define array_clear(x_) do { (x_)->count = 0; } while (0)
#define array_resize(x_, new_count_) do { \
if ((x_)->capacity < (new_count_)) { \
array_grow((x_), (new_count_)); \
} \
(x_)->count = (new_count_); \
} while (0)
#define array_reserve(x_, new_capacity_) do { \
if ((x_)->capacity < (new_capacity_)) { \
array_set_capacity((x_), (new_capacity_)); \
} \
} while (0)
void array__set_capacity(void *ptr, isize capacity, isize element_size) {
ArrayVoid *x = cast(ArrayVoid *)ptr;
GB_ASSERT(ptr != NULL);
GB_ASSERT(element_size > 0);
if (capacity == x->capacity) {
return;
}
if (capacity < x->count) {
if (x->capacity < capacity) {
isize new_capacity = ARRAY_GROW_FORMULA(x->capacity);
if (new_capacity < capacity) {
new_capacity = capacity;
}
array__set_capacity(ptr, new_capacity, element_size);
}
x->count = capacity;
}
x->e = gb_resize(x->allocator, x->e, element_size*x->capacity, element_size*capacity);
x->capacity = capacity;
}
#endif
+21 -21
View File
@@ -1,5 +1,5 @@
// This stores the information for the specify architecture of this build
typedef struct BuildContext {
struct BuildContext {
// Constants
String ODIN_OS; // target operating system
String ODIN_ARCH; // target architecture
@@ -15,7 +15,7 @@ typedef struct BuildContext {
String llc_flags;
String link_flags;
bool is_dll;
} BuildContext;
};
gb_global BuildContext build_context = {0};
@@ -35,7 +35,7 @@ String const NIX_SEPARATOR_STRING = {cast(u8 *)"/", 1};
#if defined(GB_SYSTEM_WINDOWS)
String odin_root_dir(void) {
String path = global_module_path;
Array(wchar_t) path_buf;
Array<wchar_t> path_buf;
isize len, i;
gbTempArenaMemory tmp;
wchar_t *text;
@@ -48,7 +48,7 @@ String odin_root_dir(void) {
len = 0;
for (;;) {
len = GetModuleFileNameW(NULL, &path_buf.e[0], path_buf.count);
len = GetModuleFileNameW(NULL, &path_buf[0], path_buf.count);
if (len == 0) {
return make_string(NULL, 0);
}
@@ -65,7 +65,7 @@ String odin_root_dir(void) {
GetModuleFileNameW(NULL, text, len);
path = string16_to_string(heap_allocator(), make_string16(text, len));
for (i = path.len-1; i >= 0; i--) {
u8 c = path.text[i];
u8 c = path[i];
if (c == '/' || c == '\\') {
break;
}
@@ -102,7 +102,7 @@ String odin_root_dir(void) {
len = 0;
for (;;) {
int sz = path_buf.count;
int res = _NSGetExecutablePath(&path_buf.e[0], &sz);
int res = _NSGetExecutablePath(&path_buf[0], &sz);
if(res == 0) {
len = sz;
break;
@@ -114,11 +114,11 @@ String odin_root_dir(void) {
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);
gb_memmove(text, &path_buf[0], len);
path = make_string(text, len);
for (i = path.len-1; i >= 0; i--) {
u8 c = path.text[i];
u8 c = path[i];
if (c == '/' || c == '\\') {
break;
}
@@ -158,7 +158,7 @@ String odin_root_dir(void) {
// of this compiler, it should be _good enough_.
// That said, there's no solid 100% method on Linux to get the program's
// path without checking this link. Sorry.
len = readlink("/proc/self/exe", &path_buf.e[0], path_buf.count);
len = readlink("/proc/self/exe", &path_buf[0], path_buf.count);
if(len == 0) {
return make_string(NULL, 0);
}
@@ -171,11 +171,11 @@ String odin_root_dir(void) {
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);
gb_memmove(text, &path_buf[0], len);
path = make_string(text, len);
for (i = path.len-1; i >= 0; i--) {
u8 c = path.text[i];
u8 c = path[i];
if (c == '/' || c == '\\') {
break;
}
@@ -200,10 +200,10 @@ String path_to_fullpath(gbAllocator a, String s) {
String16 string16 = string_to_string16(string_buffer_allocator, s);
String result = {0};
DWORD len = GetFullPathNameW(string16.text, 0, NULL, NULL);
DWORD len = GetFullPathNameW(&string16[0], 0, NULL, NULL);
if (len != 0) {
wchar_t *text = gb_alloc_array(string_buffer_allocator, wchar_t, len+1);
GetFullPathNameW(string16.text, len, text, NULL);
GetFullPathNameW(&string16[0], len, text, NULL);
text[len] = 0;
result = string16_to_string(a, make_string16(text, len));
}
@@ -212,7 +212,7 @@ String path_to_fullpath(gbAllocator a, String s) {
}
#elif defined(GB_SYSTEM_OSX) || defined(GB_SYSTEM_UNIX)
String path_to_fullpath(gbAllocator a, String s) {
char *p = realpath(cast(char *)s.text, 0);
char *p = realpath(cast(char *)&s[0], 0);
if(p == NULL) return make_string_c("");
return make_string_c(p);
@@ -229,8 +229,8 @@ String get_fullpath_relative(gbAllocator a, String base_dir, String path) {
u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
isize i = 0;
gb_memmove(str+i, base_dir.text, base_dir.len); i += base_dir.len;
gb_memmove(str+i, path.text, path.len);
gb_memmove(str+i, &base_dir[0], base_dir.len); i += base_dir.len;
gb_memmove(str+i, &path[0], path.len);
str[str_len] = '\0';
res = path_to_fullpath(a, make_string(str, str_len));
gb_free(heap_allocator(), str);
@@ -247,9 +247,9 @@ String get_fullpath_core(gbAllocator a, String path) {
isize str_len = module_dir.len + core_len + path.len;
u8 *str = gb_alloc_array(heap_allocator(), u8, str_len+1);
gb_memmove(str, module_dir.text, module_dir.len);
gb_memmove(str, &module_dir[0], module_dir.len);
gb_memmove(str+module_dir.len, core, core_len);
gb_memmove(str+module_dir.len+core_len, path.text, path.len);
gb_memmove(str+module_dir.len+core_len, &path[0], path.len);
str[str_len] = '\0';
res = path_to_fullpath(a, make_string(str, str_len));
@@ -294,7 +294,7 @@ void init_build_context(void) {
// NOTE(zangent): MacOS systems are x64 only, so ld doesn't have
// an architecture option. All compilation done on MacOS must be x64.
GB_ASSERT(str_eq(bc->ODIN_ARCH, str_lit("amd64")));
GB_ASSERT(bc->ODIN_ARCH == "amd64");
#define LINK_FLAG_X64 ""
#define LINK_FLAG_X86 ""
@@ -311,12 +311,12 @@ void init_build_context(void) {
#define LINK_FLAG_X86 "-arch x86"
#endif
if (str_eq(bc->ODIN_ARCH, str_lit("amd64"))) {
if (bc->ODIN_ARCH == "amd64") {
bc->word_size = 8;
bc->max_align = 16;
bc->llc_flags = str_lit("-march=x86-64 ");
bc->link_flags = str_lit(LINK_FLAG_X64 " ");
} else if (str_eq(bc->ODIN_ARCH, str_lit("x86"))) {
} else if (bc->ODIN_ARCH == "x86") {
bc->word_size = 4;
bc->max_align = 8;
bc->llc_flags = str_lit("-march=x86 ");
+26 -26
View File
@@ -13,7 +13,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
// TODO(bill): is this a good enough error message?
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
error_node(operand->expr,
"Cannot assign builtin procedure `%s` in %.*s",
"Cannot assign built-in procedure `%s` in %.*s",
expr_str,
LIT(context_name));
@@ -58,7 +58,7 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
return e->type;
}
void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) {
void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, Array<AstNode *> inits, String context_name) {
if ((lhs == NULL || lhs_count == 0) && inits.count == 0) {
return;
}
@@ -67,20 +67,20 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
// an extra allocation
ArrayOperand operands = {0};
array_init_reserve(&operands, c->tmp_allocator, 2*lhs_count);
Array<Operand> operands = {};
array_init(&operands, c->tmp_allocator, 2*lhs_count);
check_unpack_arguments(c, lhs_count, &operands, inits, true);
isize rhs_count = operands.count;
for_array(i, operands) {
if (operands.e[i].mode == Addressing_Invalid) {
if (operands[i].mode == Addressing_Invalid) {
rhs_count--;
}
}
isize max = gb_min(lhs_count, rhs_count);
for (isize i = 0; i < max; i++) {
check_init_variable(c, lhs[i], &operands.e[i], context_name);
check_init_variable(c, lhs[i], &operands[i], context_name);
}
if (rhs_count > 0 && lhs_count != rhs_count) {
error(lhs[0]->token, "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
@@ -145,7 +145,7 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def) {
// gb_printf_err("%.*s %p\n", LIT(e->token.string), e);
Type *bt = check_type_extra(c, type_expr, named);
Type *bt = check_type(c, type_expr, named);
named->Named.base = base_type(bt);
if (named->Named.base == t_invalid) {
// gb_printf("check_type_decl: %s\n", type_to_string(named));
@@ -174,7 +174,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
e->type = t;
}
Operand operand = {0};
Operand operand = {};
if (init != NULL) {
check_expr_or_type(c, &operand, init);
}
@@ -274,7 +274,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
bool is_require_results = (pd->tags & ProcTag_require_results) != 0;
if (d->scope->is_file && str_eq(e->token.string, str_lit("main"))) {
if (d->scope->is_file && e->token.string == "main") {
if (proc_type != NULL) {
TypeProc *pt = &proc_type->Proc;
if (pt->param_count != 0 ||
@@ -319,7 +319,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
}
if (is_foreign) {
MapEntity *fp = &c->info.foreigns;
auto *fp = &c->info.foreigns;
String name = e->token.string;
if (pd->foreign_name.len > 0) {
name = pd->foreign_name;
@@ -334,7 +334,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
String name = foreign_library->Ident.string;
Entity *found = scope_lookup_entity(c->context.scope, name);
if (found == NULL) {
if (str_eq(name, str_lit("_"))) {
if (name == "_") {
error_node(foreign_library, "`_` cannot be used as a value type");
} else {
error_node(foreign_library, "Undeclared name: %.*s", LIT(name));
@@ -352,7 +352,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
e->Procedure.foreign_name = name;
HashKey key = hash_string(name);
Entity **found = map_entity_get(fp, key);
Entity **found = map_get(fp, key);
if (found) {
Entity *f = *found;
TokenPos pos = f->token.pos;
@@ -365,7 +365,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
LIT(name), LIT(pos.file), pos.line, pos.column);
}
} else {
map_entity_set(fp, key, e);
map_set(fp, key, e);
}
} else {
String name = e->token.string;
@@ -374,12 +374,12 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
}
if (is_link_name || is_export) {
MapEntity *fp = &c->info.foreigns;
auto *fp = &c->info.foreigns;
e->Procedure.link_name = name;
HashKey key = hash_string(name);
Entity **found = map_entity_get(fp, key);
Entity **found = map_get(fp, key);
if (found) {
Entity *f = *found;
TokenPos pos = f->token.pos;
@@ -389,7 +389,7 @@ void check_proc_lit(Checker *c, Entity *e, DeclInfo *d) {
"\tother at %.*s(%td:%td)",
LIT(name), LIT(pos.file), pos.line, pos.column);
} else {
map_entity_set(fp, key, e);
map_set(fp, key, e);
}
}
}
@@ -408,7 +408,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
e->flags |= EntityFlag_Visited;
if (type_expr != NULL) {
e->type = check_type_extra(c, type_expr, NULL);
e->type = check_type(c, type_expr);
}
if (init_expr == NULL) {
@@ -420,7 +420,7 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
if (entities == NULL || entity_count == 1) {
GB_ASSERT(entities == NULL || entities[0] == e);
Operand operand = {0};
Operand operand = {};
check_expr(c, &operand, init_expr);
check_init_variable(c, e, &operand, str_lit("variable declaration"));
}
@@ -431,8 +431,8 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
}
}
AstNodeArray inits;
array_init_reserve(&inits, c->allocator, 1);
Array<AstNode *> inits;
array_init(&inits, c->allocator, 1);
array_add(&inits, init_expr);
check_init_variables(c, entities, entity_count, inits, str_lit("variable declaration"));
}
@@ -443,7 +443,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
}
if (d == NULL) {
DeclInfo **found = map_decl_info_get(&c->info.entities, hash_pointer(e));
DeclInfo **found = map_get(&c->info.entities, hash_pointer(e));
if (found) {
d = *found;
} else {
@@ -484,7 +484,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type) {
void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNode *body) {
GB_ASSERT(body->kind == AstNode_BlockStmt);
String proc_name = {0};
String proc_name = {};
if (token.kind == Token_Ident) {
proc_name = token.string;
} else {
@@ -511,10 +511,10 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
String name = e->token.string;
Type *t = base_type(type_deref(e->type));
if (is_type_struct(t) || is_type_raw_union(t)) {
Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
GB_ASSERT(found != NULL);
for_array(i, (*found)->elements.entries) {
Entity *f = (*found)->elements.entries.e[i].value;
Entity *f = (*found)->elements.entries[i].value;
if (f->kind == Entity_Variable) {
Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
uvar->Variable.is_immutable = is_immutable;
@@ -555,9 +555,9 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
if (decl->parent != NULL) {
// NOTE(bill): Add the dependencies from the procedure literal (lambda)
for_array(i, decl->deps.entries) {
HashKey key = decl->deps.entries.e[i].key;
HashKey key = decl->deps.entries[i].key;
Entity *e = cast(Entity *)key.ptr;
map_bool_set(&decl->parent->deps, key, true);
map_set(&decl->parent->deps, key, true);
}
}
}
File diff suppressed because it is too large Load Diff
+77 -82
View File
@@ -1,4 +1,4 @@
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
void check_stmt_list(Checker *c, Array<AstNode *> stmts, u32 flags) {
if (stmts.count == 0) {
return;
}
@@ -12,13 +12,13 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
isize max = stmts.count;
for (isize i = stmts.count-1; i >= 0; i--) {
if (stmts.e[i]->kind != AstNode_EmptyStmt) {
if (stmts[i]->kind != AstNode_EmptyStmt) {
break;
}
max--;
}
for (isize i = 0; i < max; i++) {
AstNode *n = stmts.e[i];
AstNode *n = stmts[i];
if (n->kind == AstNode_EmptyStmt) {
continue;
}
@@ -40,10 +40,10 @@ void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
}
bool check_is_terminating_list(AstNodeArray stmts) {
bool check_is_terminating_list(Array<AstNode *> stmts) {
// Iterate backwards
for (isize n = stmts.count-1; n >= 0; n--) {
AstNode *stmt = stmts.e[n];
AstNode *stmt = stmts[n];
if (stmt->kind != AstNode_EmptyStmt) {
return check_is_terminating(stmt);
}
@@ -52,9 +52,9 @@ bool check_is_terminating_list(AstNodeArray stmts) {
return false;
}
bool check_has_break_list(AstNodeArray stmts, bool implicit) {
bool check_has_break_list(Array<AstNode *> stmts, bool implicit) {
for_array(i, stmts) {
AstNode *stmt = stmts.e[i];
AstNode *stmt = stmts[i];
if (check_has_break(stmt, implicit)) {
return true;
}
@@ -137,7 +137,7 @@ bool check_is_terminating(AstNode *node) {
case_ast_node(ms, MatchStmt, node);
bool has_default = false;
for_array(i, ms->body->BlockStmt.stmts) {
AstNode *clause = ms->body->BlockStmt.stmts.e[i];
AstNode *clause = ms->body->BlockStmt.stmts[i];
ast_node(cc, CaseClause, clause);
if (cc->list.count == 0) {
has_default = true;
@@ -153,7 +153,7 @@ bool check_is_terminating(AstNode *node) {
case_ast_node(ms, TypeMatchStmt, node);
bool has_default = false;
for_array(i, ms->body->BlockStmt.stmts) {
AstNode *clause = ms->body->BlockStmt.stmts.e[i];
AstNode *clause = ms->body->BlockStmt.stmts[i];
ast_node(cc, CaseClause, clause);
if (cc->list.count == 0) {
has_default = true;
@@ -187,7 +187,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
// NOTE(bill): Ignore assignments to `_`
if (node->kind == AstNode_Ident &&
str_eq(node->Ident.string, str_lit("_"))) {
node->Ident.string == "_") {
add_entity_definition(&c->info, node, NULL);
check_assignment(c, rhs, NULL, str_lit("assignment to `_` identifier"));
if (rhs->mode == Addressing_Invalid) {
@@ -218,7 +218,7 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
if (t == t_invalid) {
continue;
}
Operand x = {0};
Operand x = {};
x.mode = Addressing_Value;
x.type = t;
if (check_is_assignable_to(c, &x, lhs.type)) {
@@ -340,11 +340,11 @@ Type *check_assignment_variable(Checker *c, Operand *rhs, AstNode *lhs_node) {
return rhs->type;
}
typedef enum MatchTypeKind {
enum MatchTypeKind {
MatchType_Invalid,
MatchType_Union,
MatchType_Any,
} MatchTypeKind;
};
MatchTypeKind check_valid_type_match_type(Type *type) {
type = type_deref(type);
@@ -384,15 +384,10 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
typedef struct TypeAndToken {
struct TypeAndToken {
Type *type;
Token token;
} TypeAndToken;
#define MAP_TYPE TypeAndToken
#define MAP_PROC map_type_and_token_
#define MAP_NAME MapTypeAndToken
#include "map.c"
};
void check_when_stmt(Checker *c, AstNodeWhenStmt *ws, u32 flags) {
flags &= ~Stmt_CheckScopeDecls;
@@ -434,7 +429,7 @@ void check_label(Checker *c, AstNode *label) {
return;
}
String name = l->name->Ident.string;
if (str_eq(name, str_lit("_"))) {
if (name == "_") {
error_node(l->name, "A label's name cannot be a blank identifier");
return;
}
@@ -448,8 +443,8 @@ void check_label(Checker *c, AstNode *label) {
bool ok = true;
for_array(i, c->context.decl->labels) {
BlockLabel bl = c->context.decl->labels.e[i];
if (str_eq(bl.name, name)) {
BlockLabel bl = c->context.decl->labels[i];
if (bl.name == name) {
error_node(label, "Duplicate label with the name `%.*s`", LIT(name));
ok = false;
break;
@@ -513,7 +508,7 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
case Entity_ImportName: {
Scope *scope = e->ImportName.scope;
for_array(i, scope->elements.entries) {
Entity *decl = scope->elements.entries.e[i].value;
Entity *decl = scope->elements.entries[i].value;
Entity *found = scope_insert_entity(c->context.scope, decl);
if (found != NULL) {
gbString expr_str = expr_to_string(expr);
@@ -535,11 +530,11 @@ bool check_using_stmt_entity(Checker *c, AstNodeUsingStmt *us, AstNode *expr, bo
Type *t = base_type(type_deref(e->type));
if (is_type_struct(t) || is_type_raw_union(t) || is_type_union(t)) {
// TODO(bill): Make it work for unions too
Scope **found_ = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
Scope **found_ = map_get(&c->info.scopes, hash_pointer(t->Record.node));
GB_ASSERT(found_ != NULL);
Scope *found = *found_;
for_array(i, found->elements.entries) {
Entity *f = found->elements.entries.e[i].value;
Entity *f = found->elements.entries[i].value;
if (f->kind == Entity_Variable) {
Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
// if (is_selector) {
@@ -645,7 +640,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
return;
}
Operand x = {0};
Operand x = {};
check_expr(c, &x, s->expr);
if (x.mode == Addressing_Invalid) {
return;
@@ -693,23 +688,23 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
// NOTE(bill): If there is a bad syntax error, rhs > lhs which would mean there would need to be
// an extra allocation
ArrayOperand operands = {0};
array_init_reserve(&operands, c->tmp_allocator, 2 * lhs_count);
Array<Operand> operands = {};
array_init(&operands, c->tmp_allocator, 2 * lhs_count);
check_unpack_arguments(c, lhs_count, &operands, as->rhs, true);
isize rhs_count = operands.count;
for_array(i, operands) {
if (operands.e[i].mode == Addressing_Invalid) {
if (operands[i].mode == Addressing_Invalid) {
rhs_count--;
}
}
isize max = gb_min(lhs_count, rhs_count);
for (isize i = 0; i < max; i++) {
check_assignment_variable(c, &operands.e[i], as->lhs.e[i]);
check_assignment_variable(c, &operands[i], as->lhs[i]);
}
if (lhs_count != rhs_count) {
error_node(as->lhs.e[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
error_node(as->lhs[0], "Assignment count mismatch `%td` = `%td`", lhs_count, rhs_count);
}
gb_temp_arena_memory_end(tmp);
@@ -732,15 +727,15 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
be->op = op;
be->op.kind = cast(TokenKind)(cast(i32)be->op.kind - (Token_AddEq - Token_Add));
// NOTE(bill): Only use the first one will be used
be->left = as->lhs.e[0];
be->right = as->rhs.e[0];
be->left = as->lhs[0];
be->right = as->rhs[0];
check_binary_expr(c, &operand, &binary_expr);
if (operand.mode == Addressing_Invalid) {
return;
}
// NOTE(bill): Only use the first one will be used
check_assignment_variable(c, &operand, as->lhs.e[0]);
check_assignment_variable(c, &operand, as->lhs[0]);
} break;
}
case_end;
@@ -794,7 +789,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
Type *proc_type = c->proc_stack.e[c->proc_stack.count-1];
Type *proc_type = c->proc_stack[c->proc_stack.count-1];
isize result_count = 0;
if (proc_type->Proc.results) {
result_count = proc_type->Proc.results->Tuple.variable_count;
@@ -816,13 +811,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_init_variables(c, variables, result_count,
rs->results, str_lit("return statement"));
// if (pos.line == 10) {
// AstNode *x = rs->results.e[0];
// AstNode *x = rs->results[0];
// gb_printf_err("%s\n", expr_to_string(x));
// gb_printf_err("%s\n", type_to_string(type_of_expr(&c->info, x)));
// }
}
} else if (rs->results.count > 0) {
error_node(rs->results.e[0], "No return values expected");
error_node(rs->results[0], "No return values expected");
}
case_end;
@@ -863,7 +858,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Type *val = NULL;
Type *idx = NULL;
Entity *entities[2] = {0};
Entity *entities[2] = {};
isize entity_count = 0;
AstNode *expr = unparen_expr(rs->expr);
@@ -943,10 +938,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
if (x.mode != Addressing_Constant) {
x.value = (ExactValue){0};
x.value = empty_exact_value;
}
if (y.mode != Addressing_Constant) {
y.value = (ExactValue){0};
y.value = empty_exact_value;
}
@@ -1032,7 +1027,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
String str = token.string;
Entity *found = NULL;
if (str_ne(str, str_lit("_"))) {
if (str != "_") {
found = current_scope_lookup_entity(c->context.scope, str);
}
if (found == NULL) {
@@ -1072,7 +1067,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case_end;
case_ast_node(ms, MatchStmt, node);
Operand x = {0};
Operand x = {};
mod_flags |= Stmt_BreakAllowed;
check_open_scope(c, node);
@@ -1089,7 +1084,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
x.type = t_bool;
x.value = exact_value_bool(true);
Token token = {0};
Token token = {};
token.pos = ast_node_token(ms->body).pos;
token.string = str_lit("true");
x.expr = ast_ident(c->curr_ast_file, token);
@@ -1106,7 +1101,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
AstNode *first_default = NULL;
ast_node(bs, BlockStmt, ms->body);
for_array(i, bs->stmts) {
AstNode *stmt = bs->stmts.e[i];
AstNode *stmt = bs->stmts[i];
AstNode *default_stmt = NULL;
if (stmt->kind == AstNode_CaseClause) {
ast_node(cc, CaseClause, stmt);
@@ -1130,11 +1125,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
}
MapTypeAndToken seen = {0}; // NOTE(bill): Multimap
map_type_and_token_init(&seen, heap_allocator());
Map<TypeAndToken> seen = {}; // NOTE(bill): Multimap
map_init(&seen, heap_allocator());
for_array(i, bs->stmts) {
AstNode *stmt = bs->stmts.e[i];
AstNode *stmt = bs->stmts[i];
if (stmt->kind != AstNode_CaseClause) {
// NOTE(bill): error handled by above multiple default checker
continue;
@@ -1142,12 +1137,12 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
ast_node(cc, CaseClause, stmt);
for_array(j, cc->list) {
AstNode *expr = unparen_expr(cc->list.e[j]);
AstNode *expr = unparen_expr(cc->list[j]);
if (is_ast_node_a_range(expr)) {
ast_node(ie, BinaryExpr, expr);
Operand lhs = {0};
Operand rhs = {0};
Operand lhs = {};
Operand rhs = {};
check_expr(c, &lhs, ie->left);
if (x.mode == Addressing_Invalid) {
continue;
@@ -1168,7 +1163,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
TokenKind op = {0};
TokenKind op = {};
Operand a = lhs;
Operand b = rhs;
@@ -1197,7 +1192,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Operand b1 = rhs;
check_comparison(c, &a1, &b1, op);
} else {
Operand y = {0};
Operand y = {};
check_expr(c, &y, expr);
if (x.mode == Addressing_Invalid ||
y.mode == Addressing_Invalid) {
@@ -1222,13 +1217,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (y.value.kind != ExactValue_Invalid) {
HashKey key = hash_exact_value(y.value);
TypeAndToken *found = map_type_and_token_get(&seen, key);
TypeAndToken *found = map_get(&seen, key);
if (found != NULL) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
isize count = map_type_and_token_multi_count(&seen, key);
isize count = multi_map_count(&seen, key);
TypeAndToken *taps = gb_alloc_array(c->tmp_allocator, TypeAndToken, count);
map_type_and_token_multi_get_all(&seen, key, taps);
multi_map_get_all(&seen, key, taps);
bool continue_outer = false;
for (isize i = 0; i < count; i++) {
@@ -1254,7 +1249,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
}
TypeAndToken tap = {y.type, ast_node_token(y.expr)};
map_type_and_token_multi_insert(&seen, key, tap);
multi_map_insert(&seen, key, tap);
}
}
}
@@ -1268,13 +1263,13 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_close_scope(c);
}
map_type_and_token_destroy(&seen);
map_destroy(&seen);
check_close_scope(c);
case_end;
case_ast_node(ms, TypeMatchStmt, node);
Operand x = {0};
Operand x = {};
mod_flags |= Stmt_BreakAllowed;
check_open_scope(c, node);
@@ -1297,8 +1292,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
syntax_error(as_token, "Expected 1 expression after `in`");
break;
}
AstNode *lhs = as->lhs.e[0];
AstNode *rhs = as->rhs.e[0];
AstNode *lhs = as->lhs[0];
AstNode *rhs = as->rhs[0];
check_expr(c, &x, rhs);
check_assignment(c, &x, NULL, str_lit("type match expression"));
@@ -1316,7 +1311,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
AstNode *first_default = NULL;
ast_node(bs, BlockStmt, ms->body);
for_array(i, bs->stmts) {
AstNode *stmt = bs->stmts.e[i];
AstNode *stmt = bs->stmts[i];
AstNode *default_stmt = NULL;
if (stmt->kind == AstNode_CaseClause) {
ast_node(cc, CaseClause, stmt);
@@ -1346,11 +1341,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
MapBool seen = {0}; // Multimap
map_bool_init(&seen, heap_allocator());
Map<bool> seen = {}; // Multimap
map_init(&seen, heap_allocator());
for_array(i, bs->stmts) {
AstNode *stmt = bs->stmts.e[i];
AstNode *stmt = bs->stmts[i];
if (stmt->kind != AstNode_CaseClause) {
// NOTE(bill): error handled by above multiple default checker
continue;
@@ -1362,9 +1357,9 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Type *case_type = NULL;
for_array(type_index, cc->list) {
AstNode *type_expr = cc->list.e[type_index];
AstNode *type_expr = cc->list[type_index];
if (type_expr != NULL) { // Otherwise it's a default expression
Operand y = {0};
Operand y = {};
check_expr_or_type(c, &y, type_expr);
if (match_type_kind == MatchType_Union) {
@@ -1391,7 +1386,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
HashKey key = hash_pointer(y.type);
bool *found = map_bool_get(&seen, key);
bool *found = map_get(&seen, key);
if (found) {
TokenPos pos = cc->token.pos;
gbString expr_str = expr_to_string(y.expr);
@@ -1403,7 +1398,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
gb_string_free(expr_str);
break;
}
map_bool_set(&seen, key, cast(bool)true);
map_set(&seen, key, cast(bool)true);
}
}
@@ -1434,7 +1429,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
check_stmt_list(c, cc->stmts, mod_flags);
check_close_scope(c);
}
map_bool_destroy(&seen);
map_destroy(&seen);
check_close_scope(c);
case_end;
@@ -1481,7 +1476,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
AstNode *ident = bs->label;
String name = ident->Ident.string;
Operand o = {0};
Operand o = {};
Entity *e = check_ident(c, &o, ident, NULL, NULL, false);
if (e == NULL) {
error_node(ident, "Undeclared label name: %.*s", LIT(name));
@@ -1502,15 +1497,15 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
return;
}
for_array(i, us->list) {
AstNode *expr = unparen_expr(us->list.e[0]);
AstNode *expr = unparen_expr(us->list[0]);
Entity *e = NULL;
bool is_selector = false;
if (expr->kind == AstNode_Ident) {
Operand o = {0};
Operand o = {};
e = check_ident(c, &o, expr, NULL, NULL, true);
} else if (expr->kind == AstNode_SelectorExpr) {
Operand o = {0};
Operand o = {};
e = check_selector(c, &o, expr, NULL);
is_selector = true;
} else if (expr->kind == AstNode_Implicit) {
@@ -1526,7 +1521,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case_ast_node(pa, PushAllocator, node);
Operand op = {0};
Operand op = {};
check_expr(c, &op, pa->expr);
check_assignment(c, &op, t_allocator, str_lit("argument to push_allocator"));
check_stmt(c, pa->body, mod_flags);
@@ -1534,7 +1529,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
case_ast_node(pa, PushContext, node);
Operand op = {0};
Operand op = {};
check_expr(c, &op, pa->expr);
check_assignment(c, &op, t_context, str_lit("argument to push_context"));
check_stmt(c, pa->body, mod_flags);
@@ -1555,7 +1550,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
for_array(i, vd->names) {
AstNode *name = vd->names.e[i];
AstNode *name = vd->names[i];
Entity *entity = NULL;
if (name->kind != AstNode_Ident) {
error_node(name, "A variable declaration must be an identifier");
@@ -1564,11 +1559,11 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
String str = token.string;
Entity *found = NULL;
// NOTE(bill): Ignore assignments to `_`
if (str_ne(str, str_lit("_"))) {
if (str != "_") {
found = current_scope_lookup_entity(c->context.scope, str);
}
if (found == NULL) {
entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, vd->flags&VarDeclFlag_immutable);
entity = make_entity_variable(c->allocator, c->context.scope, token, NULL, (vd->flags&VarDeclFlag_immutable) != 0);
entity->identifier = name;
} else {
TokenPos pos = found->token.pos;
@@ -1588,7 +1583,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Type *init_type = NULL;
if (vd->type) {
init_type = check_type_extra(c, vd->type, NULL);
init_type = check_type(c, vd->type, NULL);
if (init_type == NULL) {
init_type = t_invalid;
}
@@ -1635,10 +1630,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
Type *t = base_type(type_deref(e->type));
if (is_type_struct(t) || is_type_raw_union(t)) {
Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));
GB_ASSERT(found != NULL);
for_array(i, (*found)->elements.entries) {
Entity *f = (*found)->elements.entries.e[i].value;
Entity *f = (*found)->elements.entries[i].value;
if (f->kind == Entity_Variable) {
Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
uvar->Variable.is_immutable = is_immutable;
File diff suppressed because it is too large Load Diff
+12 -32
View File
@@ -3,7 +3,7 @@
#include <xmmintrin.h>
#endif
#define GB_NO_DEFER
// #define GB_NO_DEFER
#define GB_IMPLEMENTATION
#include "gb/gb.h"
@@ -13,22 +13,27 @@ gbAllocator heap_allocator(void) {
return gb_heap_allocator();
}
#include "unicode.c"
#include "string.c"
#include "array.c"
#include "integer128.c"
#include "murmurhash3.c"
#include "unicode.cpp"
#include "string.cpp"
#include "array.cpp"
#include "integer128.cpp"
#include "murmurhash3.cpp"
u128 fnv128a(void const *data, isize len) {
u128 o = u128_lo_hi(0x13bull, 0x1000000ull);
u128 h = u128_lo_hi(0x62b821756295c58dull, 0x6c62272e07bb0142ull);
u8 const *bytes = cast(u8 const *)data;
for (isize i = 0; i < len; i++) {
h = u128_mul(u128_xor(h, u128_from_u64(bytes[i])), o);
h.lo ^= bytes[i];
h = h * o;
}
return h;
}
#include "map.cpp"
gb_global String global_module_path = {0};
gb_global bool global_module_path_set = false;
@@ -43,8 +48,6 @@ gbAllocator scratch_allocator(void) {
return gb_scratch_allocator(&scratch_memory);
}
typedef struct DynamicArenaBlock DynamicArenaBlock;
typedef struct DynamicArena DynamicArena;
struct DynamicArenaBlock {
DynamicArenaBlock *prev;
@@ -236,27 +239,4 @@ f64 gb_sqrt(f64 x) {
} \
} while (0)
////////////////////////////////////////////////////////////////
//
// Generic Data Structures
//
////////////////////////////////////////////////////////////////
typedef Array(i32) Array_i32;
typedef Array(isize) Array_isize;
#define MAP_TYPE String
#define MAP_PROC map_string_
#define MAP_NAME MapString
#include "map.c"
#define MAP_TYPE bool
#define MAP_PROC map_bool_
#define MAP_NAME MapBool
#include "map.c"
#define MAP_TYPE isize
#define MAP_PROC map_isize_
#define MAP_NAME MapIsize
#include "map.c"
+18 -18
View File
@@ -1,7 +1,7 @@
typedef struct Scope Scope;
typedef struct Checker Checker;
typedef struct Type Type;
typedef struct DeclInfo DeclInfo;
struct Scope;
struct Checker;
struct Type;
struct DeclInfo;
// typedef enum BuiltinProcId BuiltinProcId;
@@ -19,12 +19,12 @@ typedef struct DeclInfo DeclInfo;
ENTITY_KIND(Nil) \
ENTITY_KIND(Label)
typedef enum EntityKind {
enum EntityKind {
#define ENTITY_KIND(k) GB_JOIN2(Entity_, k),
ENTITY_KINDS
#undef ENTITY_KIND
Entity_Count,
} EntityKind;
};
String const entity_strings[] = {
#define ENTITY_KIND(k) {cast(u8 *)#k, gb_size_of(#k)-1},
@@ -32,7 +32,7 @@ String const entity_strings[] = {
#undef ENTITY_KIND
};
typedef enum EntityFlag {
enum EntityFlag {
EntityFlag_Visited = 1<<0,
EntityFlag_Used = 1<<1,
EntityFlag_Using = 1<<2,
@@ -45,24 +45,23 @@ typedef enum EntityFlag {
EntityFlag_Value = 1<<9,
EntityFlag_Sret = 1<<10,
EntityFlag_BitFieldValue = 1<<11,
} EntityFlag;
};
// Zero value means the overloading process is not yet done
typedef enum OverloadKind {
enum OverloadKind {
Overload_Unknown,
Overload_No,
Overload_Yes,
} OverloadKind;
};
typedef enum EntityAliasKind {
enum EntityAliasKind {
EntityAlias_Invalid,
EntityAlias_Type,
EntityAlias_Entity,
} EntityAliasKind;
};
// An Entity is a named "thing" in the language
typedef struct Entity Entity;
struct Entity {
EntityKind kind;
u64 id;
@@ -82,10 +81,11 @@ struct Entity {
ExactValue value;
} Constant;
struct {
i32 field_index;
i32 field_src_index;
bool is_immutable;
bool is_thread_local;
i32 field_index;
i32 field_src_index;
bool is_immutable;
bool is_thread_local;
ExactValue default_value;
} Variable;
struct {
bool is_type_alias;
@@ -148,7 +148,7 @@ bool is_entity_exported(Entity *e) {
if (name.len == 0) {
return false;
}
return name.text[0] != '_';
return name[0] != '_';
}
gb_global u64 global_entity_id = 0;
+40 -38
View File
@@ -3,13 +3,14 @@
// TODO(bill): Big numbers
// IMPORTANT TODO(bill): This needs to be completely fixed!!!!!!!!
typedef struct AstNode AstNode;
struct AstNode;
struct HashKey;
typedef struct Complex128 {
struct Complex128 {
f64 real, imag;
} Complex128;
};
typedef enum ExactValueKind {
enum ExactValueKind {
ExactValue_Invalid,
ExactValue_Bool,
@@ -21,9 +22,9 @@ typedef enum ExactValueKind {
ExactValue_Compound, // TODO(bill): Is this good enough?
ExactValue_Count,
} ExactValueKind;
};
typedef struct ExactValue {
struct ExactValue {
ExactValueKind kind;
union {
bool value_bool;
@@ -34,7 +35,9 @@ typedef struct ExactValue {
Complex128 value_complex;
AstNode * value_compound;
};
} ExactValue;
};
gb_global ExactValue const empty_exact_value = {};
HashKey hash_exact_value(ExactValue v) {
return hashing_proc(&v, gb_size_of(ExactValue));
@@ -191,7 +194,7 @@ ExactValue exact_value_from_basic_literal(Token token) {
case Token_Float: return exact_value_float_from_string(token.string);
case Token_Imag: {
String str = token.string;
Rune last_rune = cast(Rune)str.text[str.len-1];
Rune last_rune = cast(Rune)str[str.len-1];
str.len--; // Ignore the `i|j|k`
f64 imag = float_from_string(str);
@@ -314,7 +317,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
return v;
case ExactValue_Integer: {
ExactValue i = v;
i.value_integer = i128_neg(i.value_integer);
i.value_integer = -i.value_integer;
return i;
}
case ExactValue_Float: {
@@ -336,7 +339,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
case ExactValue_Invalid:
return v;
case ExactValue_Integer:
i = i128_not(v.value_integer);
i = ~v.value_integer;
break;
default:
goto failure;
@@ -346,7 +349,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
// limited to the types precision
// IMPORTANT NOTE(bill): Max precision is 64 bits as that's how integers are stored
if (0 < precision && precision < 128) {
i = i128_and(i, i128_not(i128_shl(I128_NEG_ONE, precision)));
i = i & ~(I128_NEG_ONE << precision);
}
return exact_value_i128(i);
@@ -364,7 +367,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
failure:
GB_PANIC("Invalid unary operation, %.*s", LIT(token_strings[op]));
ExactValue error_value = {0};
ExactValue error_value = {};
return error_value;
}
@@ -458,19 +461,19 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
i128 b = y.value_integer;
i128 c = I128_ZERO;
switch (op) {
case Token_Add: c = i128_add(a, b); break;
case Token_Sub: c = i128_sub(a, b); break;
case Token_Mul: c = i128_mul(a, b); break;
case Token_Add: c = a + b; break;
case Token_Sub: c = a - b; break;
case Token_Mul: c = a * b; break;
case Token_Quo: return exact_value_float(fmod(i128_to_f64(a), i128_to_f64(b)));
case Token_QuoEq: c = i128_quo(a, b); break; // NOTE(bill): Integer division
case Token_Mod: c = i128_mod(a, b); break;
case Token_ModMod: c = i128_mod(i128_add(i128_mod(a, b), b), b); break;
case Token_And: c = i128_and (a, b); break;
case Token_Or: c = i128_or (a, b); break;
case Token_Xor: c = i128_xor (a, b); break;
case Token_AndNot: c = i128_and_not(a, b); break;
case Token_Shl: c = i128_shl (a, i128_to_u64(b)); break;
case Token_Shr: c = i128_shr (a, i128_to_u64(b)); break;
case Token_QuoEq: c = a / b; break; // NOTE(bill): Integer division
case Token_Mod: c = a % b; break;
case Token_ModMod: c = ((a % b) + b) % b; break;
case Token_And: c = a & b; break;
case Token_Or: c = a | b; break;
case Token_Xor: c = a ^ b; break;
case Token_AndNot: c = i128_and_not(a, b); break;
case Token_Shl: c = a << i128_to_u64(b); break;
case Token_Shr: c = a >> i128_to_u64(b); break;
default: goto error;
}
@@ -523,7 +526,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};
ExactValue error_value = {};
// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op));
return error_value;
}
@@ -557,12 +560,12 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
i128 a = x.value_integer;
i128 b = y.value_integer;
switch (op) {
case Token_CmpEq: return i128_eq(a, b);
case Token_NotEq: return i128_ne(a, b);
case Token_Lt: return i128_lt(a, b);
case Token_LtEq: return i128_le(a, b);
case Token_Gt: return i128_gt(a, b);
case Token_GtEq: return i128_ge(a, b);
case Token_CmpEq: return a == b;
case Token_NotEq: return a != b;
case Token_Lt: return a < b;
case Token_LtEq: return a <= b;
case Token_Gt: return a > b;
case Token_GtEq: return a >= b;
}
} break;
@@ -593,15 +596,14 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
case ExactValue_String: {
String a = x.value_string;
String b = y.value_string;
isize len = gb_min(a.len, b.len);
// TODO(bill): gb_memcompare is used because the strings are UTF-8
switch (op) {
case Token_CmpEq: return gb_memcompare(a.text, b.text, len) == 0;
case Token_NotEq: return gb_memcompare(a.text, b.text, len) != 0;
case Token_Lt: return gb_memcompare(a.text, b.text, len) < 0;
case Token_LtEq: return gb_memcompare(a.text, b.text, len) <= 0;
case Token_Gt: return gb_memcompare(a.text, b.text, len) > 0;
case Token_GtEq: return gb_memcompare(a.text, b.text, len) >= 0;
case Token_CmpEq: return a == b;
case Token_NotEq: return a != b;
case Token_Lt: return a < b;
case Token_LtEq: return a <= b;
case Token_Gt: return a > b;
case Token_GtEq: return a >= b;
}
} break;
}
+111 -14
View File
@@ -1,16 +1,25 @@
typedef struct u128 {u64 lo; u64 hi;} u128;
typedef struct i128 {u64 lo; i64 hi;} i128;
#define BIT128_U64_HIGHBIT 0x8000000000000000ul
#define BIT128_U64_BITS62 0x7ffffffffffffffful
#define BIT128_U64_ALLBITS 0xfffffffffffffffful
#if defined(GB_COMPILER_MSVC) && defined(GB_ARCH_64_BIT) && defined(GB_CPU_X86)
#define MSVC_AMD64_INTRINSICS
#include <intrin.h>
#pragma intrinsic(_mul128)
#endif
#define BIT128_U64_HIGHBIT 0x8000000000000000ull
#define BIT128_U64_BITS62 0x7fffffffffffffffull
#define BIT128_U64_ALLBITS 0xffffffffffffffffull
typedef struct u128 { u64 lo; u64 hi; } u128;
typedef struct i128 { u64 lo; i64 hi; } i128;
static u128 const U128_ZERO = {0, 0};
static u128 const U128_ONE = {1, 0};
static i128 const I128_ZERO = {0, 0};
static i128 const I128_ONE = {1, 0};
static u128 const U128_NEG_ONE = {BIT128_U64_ALLBITS, BIT128_U64_ALLBITS};
static i128 const I128_NEG_ONE = {BIT128_U64_ALLBITS, BIT128_U64_ALLBITS};
static i128 const I128_NEG_ONE = {BIT128_U64_ALLBITS, cast(i64)BIT128_U64_ALLBITS};
u128 u128_lo_hi (u64 lo, u64 hi);
u128 u128_from_u32 (u32 u);
@@ -84,6 +93,48 @@ void i128_divide (i128 num, i128 den, i128 *quo, i128 *rem);
i128 i128_quo (i128 a, i128 b);
i128 i128_mod (i128 a, i128 b);
bool operator==(u128 a, u128 b) { return u128_eq(a, b); }
bool operator!=(u128 a, u128 b) { return u128_ne(a, b); }
bool operator< (u128 a, u128 b) { return u128_lt(a, b); }
bool operator> (u128 a, u128 b) { return u128_gt(a, b); }
bool operator<=(u128 a, u128 b) { return u128_le(a, b); }
bool operator>=(u128 a, u128 b) { return u128_ge(a, b); }
u128 operator+(u128 a, u128 b) { return u128_add(a, b); }
u128 operator-(u128 a, u128 b) { return u128_sub(a, b); }
u128 operator*(u128 a, u128 b) { return u128_mul(a, b); }
u128 operator/(u128 a, u128 b) { return u128_quo(a, b); }
u128 operator%(u128 a, u128 b) { return u128_mod(a, b); }
u128 operator&(u128 a, u128 b) { return u128_and(a, b); }
u128 operator|(u128 a, u128 b) { return u128_or (a, b); }
u128 operator^(u128 a, u128 b) { return u128_xor(a, b); }
u128 operator~(u128 a) { return u128_not(a); }
u128 operator+(u128 a) { return a; }
u128 operator-(u128 a) { return u128_neg(a); }
u128 operator<<(u128 a, u32 b) { return u128_shl(a, b); }
u128 operator>>(u128 a, u32 b) { return u128_shr(a, b); }
bool operator==(i128 a, i128 b) { return i128_eq(a, b); }
bool operator!=(i128 a, i128 b) { return i128_ne(a, b); }
bool operator< (i128 a, i128 b) { return i128_lt(a, b); }
bool operator> (i128 a, i128 b) { return i128_gt(a, b); }
bool operator<=(i128 a, i128 b) { return i128_le(a, b); }
bool operator>=(i128 a, i128 b) { return i128_ge(a, b); }
i128 operator+(i128 a, i128 b) { return i128_add(a, b); }
i128 operator-(i128 a, i128 b) { return i128_sub(a, b); }
i128 operator*(i128 a, i128 b) { return i128_mul(a, b); }
i128 operator/(i128 a, i128 b) { return i128_quo(a, b); }
i128 operator%(i128 a, i128 b) { return i128_mod(a, b); }
i128 operator&(i128 a, i128 b) { return i128_and(a, b); }
i128 operator|(i128 a, i128 b) { return i128_or (a, b); }
i128 operator^(i128 a, i128 b) { return i128_xor(a, b); }
i128 operator~(i128 a) { return i128_not(a); }
i128 operator+(i128 a) { return a; }
i128 operator-(i128 a) { return i128_neg(a); }
i128 operator<<(i128 a, u32 b) { return i128_shl(a, b); }
i128 operator>>(i128 a, u32 b) { return i128_shr(a, b); }
////////////////////////////////////////////////////////////////
@@ -99,7 +150,7 @@ u64 bit128__digit_value(Rune r) {
return 16; // NOTE(bill): Larger than highest possible
}
u128 u128_lo_hi(u64 lo, u64 hi) { return (u128){lo, hi}; }
u128 u128_lo_hi(u64 lo, u64 hi) { return u128{lo, hi}; }
u128 u128_from_u32(u32 u) { return u128_lo_hi(cast(u64)u, 0); }
u128 u128_from_u64(u64 u) { return u128_lo_hi(cast(u64)u, 0); }
u128 u128_from_i64(i64 u) { return u128_lo_hi(cast(u64)u, u < 0 ? -1 : 0); }
@@ -109,8 +160,8 @@ u128 u128_from_string(String string) {
// TODO(bill): Allow for numbers with underscores in them
u64 base = 10;
bool has_prefix = false;
if (string.len > 2 && string.text[0] == '0') {
switch (string.text[1]) {
if (string.len > 2 && string[0] == '0') {
switch (string[1]) {
case 'b': base = 2; has_prefix = true; break;
case 'o': base = 8; has_prefix = true; break;
case 'd': base = 10; has_prefix = true; break;
@@ -160,8 +211,8 @@ i128 i128_from_string(String string) {
// TODO(bill): Allow for numbers with underscores in them
u64 base = 10;
bool has_prefix = false;
if (string.len > 2 && string.text[0] == '0') {
switch (string.text[1]) {
if (string.len > 2 && string[0] == '0') {
switch (string[1]) {
case 'b': base = 2; has_prefix = true; break;
case 'o': base = 8; has_prefix = true; break;
case 'd': base = 10; has_prefix = true; break;
@@ -332,7 +383,11 @@ u128 u128_shl(u128 a, u32 n) {
if (n >= 128) {
return u128_lo_hi(0, 0);
}
#if 0 && defined(MSVC_AMD64_INTRINSICS)
a.hi = __shiftleft128(a.lo, a.hi, n);
a.lo = a.lo << n;
return a;
#else
if (n >= 64) {
n -= 64;
a.hi = a.lo;
@@ -347,13 +402,18 @@ u128 u128_shl(u128 a, u32 n) {
a.lo <<= n;
}
return a;
#endif
}
u128 u128_shr(u128 a, u32 n) {
if (n >= 128) {
return u128_lo_hi(0, 0);
}
#if 0 && defined(MSVC_AMD64_INTRINSICS)
a.lo = __shiftright128(a.lo, a.hi, n);
a.hi = a.hi >> n;
return a;
#else
if (n >= 64) {
n -= 64;
a.lo = a.hi;
@@ -367,6 +427,7 @@ u128 u128_shr(u128 a, u32 n) {
a.hi >>= n;
}
return a;
#endif
}
@@ -383,6 +444,14 @@ u128 u128_mul(u128 a, u128 b) {
return a;
}
#if defined(MSVC_AMD64_INTRINSICS)
if (a.hi == 0 && b.hi == 0) {
a.lo = _umul128(a.lo, b.lo, &a.hi);
return a;
}
#endif
u128 res = {0};
u128 t = b;
for (u32 i = 0; i < 128; i++) {
@@ -396,6 +465,8 @@ u128 u128_mul(u128 a, u128 b) {
return res;
}
bool u128_hibit(u128 *d) { return (d->hi & BIT128_U64_HIGHBIT) != 0; }
void u128_divide(u128 num, u128 den, u128 *quo, u128 *rem) {
if (u128_eq(den, U128_ZERO)) {
if (quo) *quo = u128_from_u64(num.lo/den.lo);
@@ -406,7 +477,7 @@ void u128_divide(u128 num, u128 den, u128 *quo, u128 *rem) {
u128 x = U128_ONE;
u128 r = U128_ZERO;
while (u128_ge(n, d) && ((u128_shr(d, 128-1).lo&1) == 0)) {
while (u128_ge(n, d) && !u128_hibit(&d)) {
x = u128_shl(x, 1);
d = u128_shl(d, 1);
}
@@ -427,11 +498,18 @@ void u128_divide(u128 num, u128 den, u128 *quo, u128 *rem) {
}
u128 u128_quo(u128 a, u128 b) {
if (a.hi == 0 && b.hi == 0) {
return u128_from_u64(a.lo/b.lo);
}
u128 res = {0};
u128_divide(a, b, &res, NULL);
return res;
}
u128 u128_mod(u128 a, u128 b) {
if (a.hi == 0 && b.hi == 0) {
return u128_from_u64(a.lo%b.lo);
}
u128 res = {0};
u128_divide(a, b, NULL, &res);
return res;
@@ -491,6 +569,11 @@ i128 i128_shl(i128 a, u32 n) {
return i128_lo_hi(0, 0);
}
#if 0 && defined(MSVC_AMD64_INTRINSICS)
a.hi = __shiftleft128(a.lo, a.hi, n);
a.lo = a.lo << n;
return a;
#else
if (n >= 64) {
n -= 64;
a.hi = a.lo;
@@ -505,6 +588,7 @@ i128 i128_shl(i128 a, u32 n) {
a.lo <<= n;
}
return a;
#endif
}
i128 i128_shr(i128 a, u32 n) {
@@ -512,6 +596,11 @@ i128 i128_shr(i128 a, u32 n) {
return i128_lo_hi(0, 0);
}
#if 0 && defined(MSVC_AMD64_INTRINSICS)
a.lo = __shiftright128(a.lo, a.hi, n);
a.hi = a.hi >> n;
return a;
#else
if (n >= 64) {
n -= 64;
a.lo = a.hi;
@@ -525,6 +614,7 @@ i128 i128_shr(i128 a, u32 n) {
a.hi >>= n;
}
return a;
#endif
}
@@ -541,6 +631,13 @@ i128 i128_mul(i128 a, i128 b) {
return a;
}
#if defined(MSVC_AMD64_INTRINSICS)
if (a.hi == 0 && b.hi == 0) {
a.lo = _mul128(a.lo, b.lo, &a.hi);
return a;
}
#endif
i128 res = {0};
i128 t = b;
for (u32 i = 0; i < 128; i++) {
+385 -366
View File
File diff suppressed because it is too large Load Diff
+43 -43
View File
@@ -1,6 +1,6 @@
// Optimizations for the IR code
void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
void ir_opt_add_operands(Array<irValue *> *ops, irInstr *i) {
switch (i->kind) {
case irInstr_Comment:
break;
@@ -48,7 +48,7 @@ void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
break;
case irInstr_Phi:
for_array(j, i->Phi.edges) {
array_add(ops, i->Phi.edges.e[j]);
array_add(ops, i->Phi.edges[j]);
}
break;
case irInstr_Unreachable:
@@ -97,24 +97,24 @@ void ir_opt_add_operands(irValueArray *ops, irInstr *i) {
void ir_opt_block_replace_pred(irBlock *b, irBlock *from, irBlock *to) {
for_array(i, b->preds) {
irBlock *pred = b->preds.e[i];
irBlock *pred = b->preds[i];
if (pred == from) {
b->preds.e[i] = to;
b->preds[i] = to;
}
}
}
void ir_opt_block_replace_succ(irBlock *b, irBlock *from, irBlock *to) {
for_array(i, b->succs) {
irBlock *succ = b->succs.e[i];
irBlock *succ = b->succs[i];
if (succ == from) {
b->succs.e[i] = to;
b->succs[i] = to;
}
}
}
bool ir_opt_block_has_phi(irBlock *b) {
return b->instrs.e[0]->Instr.kind == irInstr_Phi;
return b->instrs[0]->Instr.kind == irInstr_Phi;
}
@@ -126,10 +126,10 @@ bool ir_opt_block_has_phi(irBlock *b) {
irValueArray ir_get_block_phi_nodes(irBlock *b) {
irValueArray phis = {0};
Array<irValue *> ir_get_block_phi_nodes(irBlock *b) {
Array<irValue *> phis = {0};
for_array(i, b->instrs) {
irInstr *instr = &b->instrs.e[i]->Instr;
irInstr *instr = &b->instrs[i]->Instr;
if (instr->kind != irInstr_Phi) {
phis = b->instrs;
phis.count = i;
@@ -140,22 +140,22 @@ irValueArray ir_get_block_phi_nodes(irBlock *b) {
}
void ir_remove_pred(irBlock *b, irBlock *p) {
irValueArray phis = ir_get_block_phi_nodes(b);
Array<irValue *> phis = ir_get_block_phi_nodes(b);
isize i = 0;
for_array(j, b->preds) {
irBlock *pred = b->preds.e[j];
irBlock *pred = b->preds[j];
if (pred != p) {
b->preds.e[i] = b->preds.e[j];
b->preds[i] = b->preds[j];
for_array(k, phis) {
irInstrPhi *phi = &phis.e[k]->Instr.Phi;
phi->edges.e[i] = phi->edges.e[j];
irInstrPhi *phi = &phis[k]->Instr.Phi;
phi->edges[i] = phi->edges[j];
}
i++;
}
}
b->preds.count = i;
for_array(k, phis) {
irInstrPhi *phi = &phis.e[k]->Instr.Phi;
irInstrPhi *phi = &phis[k]->Instr.Phi;
phi->edges.count = i;
}
@@ -164,13 +164,13 @@ void ir_remove_pred(irBlock *b, irBlock *p) {
void ir_remove_dead_blocks(irProcedure *proc) {
isize j = 0;
for_array(i, proc->blocks) {
irBlock *b = proc->blocks.e[i];
irBlock *b = proc->blocks[i];
if (b == NULL) {
continue;
}
// NOTE(bill): Swap order
b->index = j;
proc->blocks.e[j++] = b;
proc->blocks[j++] = b;
}
proc->blocks.count = j;
}
@@ -180,7 +180,7 @@ void ir_mark_reachable(irBlock *b) {
isize const BLACK = -1;
b->index = BLACK;
for_array(i, b->succs) {
irBlock *succ = b->succs.e[i];
irBlock *succ = b->succs[i];
if (succ->index == WHITE) {
ir_mark_reachable(succ);
}
@@ -191,23 +191,23 @@ void ir_remove_unreachable_blocks(irProcedure *proc) {
isize const WHITE = 0;
isize const BLACK = -1;
for_array(i, proc->blocks) {
proc->blocks.e[i]->index = WHITE;
proc->blocks[i]->index = WHITE;
}
ir_mark_reachable(proc->blocks.e[0]);
ir_mark_reachable(proc->blocks[0]);
for_array(i, proc->blocks) {
irBlock *b = proc->blocks.e[i];
irBlock *b = proc->blocks[i];
if (b->index == WHITE) {
for_array(j, b->succs) {
irBlock *c = b->succs.e[j];
irBlock *c = b->succs[j];
if (c->index == BLACK) {
ir_remove_pred(c, b);
}
}
// NOTE(bill): Mark as empty but don't actually free it
// As it's been allocated with an arena
proc->blocks.e[i] = NULL;
proc->blocks[i] = NULL;
}
}
ir_remove_dead_blocks(proc);
@@ -217,7 +217,7 @@ bool ir_opt_block_fusion(irProcedure *proc, irBlock *a) {
if (a->succs.count != 1) {
return false;
}
irBlock *b = a->succs.e[0];
irBlock *b = a->succs[0];
if (b->preds.count != 1) {
return false;
}
@@ -228,21 +228,21 @@ bool ir_opt_block_fusion(irProcedure *proc, irBlock *a) {
array_pop(&a->instrs); // Remove branch at end
for_array(i, b->instrs) {
array_add(&a->instrs, b->instrs.e[i]);
ir_set_instr_parent(b->instrs.e[i], a);
array_add(&a->instrs, b->instrs[i]);
ir_set_instr_parent(b->instrs[i], a);
}
array_clear(&a->succs);
for_array(i, b->succs) {
array_add(&a->succs, b->succs.e[i]);
array_add(&a->succs, b->succs[i]);
}
// Fix preds links
for_array(i, b->succs) {
ir_opt_block_replace_pred(b->succs.e[i], b, a);
ir_opt_block_replace_pred(b->succs[i], b, a);
}
proc->blocks.e[b->index] = NULL;
proc->blocks[b->index] = NULL;
return true;
}
@@ -254,7 +254,7 @@ void ir_opt_blocks(irProcedure *proc) {
while (changed) {
changed = false;
for_array(i, proc->blocks) {
irBlock *b = proc->blocks.e[i];
irBlock *b = proc->blocks[i];
if (b == NULL) {
continue;
}
@@ -273,20 +273,20 @@ void ir_opt_blocks(irProcedure *proc) {
void ir_opt_build_referrers(irProcedure *proc) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
irValueArray ops = {0}; // NOTE(bill): Act as a buffer
array_init_reserve(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
Array<irValue *> ops = {0}; // NOTE(bill): Act as a buffer
array_init(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
for_array(i, proc->blocks) {
irBlock *b = proc->blocks.e[i];
irBlock *b = proc->blocks[i];
for_array(j, b->instrs) {
irValue *instr = b->instrs.e[j];
irValue *instr = b->instrs[j];
array_clear(&ops);
ir_opt_add_operands(&ops, &instr->Instr);
for_array(k, ops) {
irValue *op = ops.e[k];
irValue *op = ops[k];
if (op == NULL) {
continue;
}
irValueArray *refs = ir_value_referrers(op);
Array<irValue *> *refs = ir_value_referrers(op);
if (refs != NULL) {
array_add(refs, instr);
}
@@ -324,7 +324,7 @@ i32 ir_lt_depth_first_search(irLTState *lt, irBlock *p, i32 i, irBlock **preorde
lt->sdom[p->index] = p;
ir_lt_link(lt, NULL, p);
for_array(index, p->succs) {
irBlock *q = p->succs.e[index];
irBlock *q = p->succs[index];
if (lt->sdom[q->index] == NULL) {
lt->parent[q->index] = p;
i = ir_lt_depth_first_search(lt, q, i, preorder);
@@ -354,7 +354,7 @@ irDomPrePost ir_opt_number_dom_tree(irBlock *v, i32 pre, i32 post) {
v->dom.pre = pre++;
for_array(i, v->dom.children) {
result = ir_opt_number_dom_tree(v->dom.children.e[i], result.pre, result.post);
result = ir_opt_number_dom_tree(v->dom.children[i], result.pre, result.post);
}
v->dom.post = post++;
@@ -381,7 +381,7 @@ void ir_opt_build_dom_tree(irProcedure *proc) {
irBlock **preorder = &buf[3*n];
irBlock **buckets = &buf[4*n];
irBlock *root = proc->blocks.e[0];
irBlock *root = proc->blocks[0];
// Step 1 - number vertices
i32 pre_num = ir_lt_depth_first_search(&lt, root, 0, preorder);
@@ -403,7 +403,7 @@ void ir_opt_build_dom_tree(irProcedure *proc) {
// Step 2 - Compute all sdoms
lt.sdom[w->index] = lt.parent[w->index];
for_array(pred_index, w->preds) {
irBlock *v = w->preds.e[pred_index];
irBlock *v = w->preds[pred_index];
irBlock *u = ir_lt_eval(&lt, v);
if (lt.sdom[u->index]->dom.pre < lt.sdom[w->index]->dom.pre) {
lt.sdom[w->index] = lt.sdom[u->index];
@@ -438,7 +438,7 @@ void ir_opt_build_dom_tree(irProcedure *proc) {
}
// Calculate children relation as inverse of idom
if (w->dom.idom->dom.children.e == NULL) {
if (w->dom.idom->dom.children.data == NULL) {
// TODO(bill): Is this good enough for memory allocations?
array_init(&w->dom.idom->dom.children, heap_allocator());
}
@@ -461,7 +461,7 @@ void ir_opt_tree(irGen *s) {
s->opt_called = true;
for_array(member_index, s->module.procs) {
irProcedure *proc = s->module.procs.e[member_index];
irProcedure *proc = s->module.procs[member_index];
if (proc->blocks.count == 0) { // Prototype/external procedure
continue;
}
+31 -31
View File
@@ -1,8 +1,8 @@
typedef struct irFileBuffer {
struct irFileBuffer {
gbVirtualMemory vm;
isize offset;
gbFile * output;
} irFileBuffer;
};
void ir_file_buffer_init(irFileBuffer *f, gbFile *output) {
isize size = 8*gb_virtual_memory_page_size(NULL);
@@ -39,7 +39,7 @@ void ir_file_buffer_write(irFileBuffer *f, void *data, isize len) {
void ir_fprintf(irFileBuffer *f, char *fmt, ...) {
va_list va;
va_start(va, fmt);
char buf[4096] = {0};
char buf[4096] = {};
isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va);
ir_file_buffer_write(f, buf, len-1);
va_end(va);
@@ -48,7 +48,7 @@ void ir_fprint_string(irFileBuffer *f, String s) {
ir_file_buffer_write(f, s.text, s.len);
}
void ir_fprint_i128(irFileBuffer *f, i128 i) {
char buf[200] = {0};
char buf[200] = {};
String str = i128_to_string(i, buf, gb_size_of(buf)-1);
ir_fprint_string(f, str);
}
@@ -81,7 +81,7 @@ bool ir_valid_char(u8 c) {
void ir_print_escape_string(irFileBuffer *f, String name, bool print_quotes, bool prefix_with_dot) {
isize extra = 0;
for (isize i = 0; i < name.len; i++) {
u8 c = name.text[i];
u8 c = name[i];
if (!ir_valid_char(c)) {
extra += 2;
}
@@ -111,7 +111,7 @@ void ir_print_escape_string(irFileBuffer *f, String name, bool print_quotes, boo
}
for (isize i = 0; i < name.len; i++) {
u8 c = name.text[i];
u8 c = name[i];
if (ir_valid_char(c)) {
buf[j++] = c;
} else {
@@ -306,7 +306,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t) {
case Type_Named:
if (is_type_struct(t) || is_type_union(t)) {
String *name = map_string_get(&m->entity_names, hash_pointer(t->Named.type_name));
String *name = map_get(&m->entity_names, hash_pointer(t->Named.type_name));
GB_ASSERT_MSG(name != NULL, "%.*s", LIT(t->Named.name));
ir_print_encoded_local(f, *name);
} else {
@@ -497,7 +497,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
if (i > 0) {
ir_fprintf(f, ", ");
}
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
GB_ASSERT(tav.mode != Addressing_Invalid);
ir_print_compound_element(f, m, tav.value, elem_type);
}
@@ -527,7 +527,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
ir_fprintf(f, "][");
if (elem_count == 1 && type->Vector.count > 1) {
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[0]);
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[0]);
GB_ASSERT(tav.mode != Addressing_Invalid);
for (isize i = 0; i < type->Vector.count; i++) {
@@ -541,7 +541,7 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
if (i > 0) {
ir_fprintf(f, ", ");
}
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
GB_ASSERT(tav.mode != Addressing_Invalid);
ir_print_compound_element(f, m, tav.value, elem_type);
}
@@ -563,25 +563,25 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
ExactValue *values = gb_alloc_array(m->tmp_allocator, ExactValue, value_count);
if (cl->elems.e[0]->kind == AstNode_FieldValue) {
if (cl->elems[0]->kind == AstNode_FieldValue) {
isize elem_count = cl->elems.count;
for (isize i = 0; i < elem_count; i++) {
ast_node(fv, FieldValue, cl->elems.e[i]);
ast_node(fv, FieldValue, cl->elems[i]);
String name = fv->field->Ident.string;
TypeAndValue tav = type_and_value_of_expr(m->info, fv->value);
GB_ASSERT(tav.mode != Addressing_Invalid);
Selection sel = lookup_field(m->allocator, type, name, false);
Entity *f = type->Record.fields[sel.index.e[0]];
Entity *f = type->Record.fields[sel.index[0]];
values[f->Variable.field_index] = tav.value;
}
} else {
for (isize i = 0; i < value_count; i++) {
Entity *f = type->Record.fields_in_src_order[i];
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems.e[i]);
ExactValue val = {0};
TypeAndValue tav = type_and_value_of_expr(m->info, cl->elems[i]);
ExactValue val = {};
if (tav.mode != Addressing_Invalid) {
val = tav.value;
}
@@ -891,11 +891,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
ir_fprintf(f, ", ");
}
irValue *edge = instr->Phi.edges.e[i];
irValue *edge = instr->Phi.edges[i];
irBlock *block = NULL;
if (instr->parent != NULL &&
i < instr->parent->preds.count) {
block = instr->parent->preds.e[i];
block = instr->parent->preds[i];
}
ir_fprintf(f, "[ ");
@@ -1500,8 +1500,8 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
ir_fprintf(f, " noalias");
}
if (proc->body != NULL) {
if (!str_eq(e->token.string, str_lit("")) &&
!str_eq(e->token.string, str_lit("_"))) {
if (e->token.string != "" &&
e->token.string != "_") {
ir_fprintf(f, " ");
ir_print_encoded_local(f, e->token.string);
} else {
@@ -1523,7 +1523,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
if (proc->entity != NULL) {
if (proc->body != NULL) {
irDebugInfo **di_ = map_ir_debug_info_get(&proc->module->debug_info, hash_pointer(proc->entity));
irDebugInfo **di_ = map_get(&proc->module->debug_info, hash_pointer(proc->entity));
if (di_ != NULL) {
irDebugInfo *di = *di_;
GB_ASSERT(di->kind == irDebugInfo_Proc);
@@ -1538,14 +1538,14 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
ir_fprintf(f, "{\n");
for_array(i, proc->blocks) {
irBlock *block = proc->blocks.e[i];
irBlock *block = proc->blocks[i];
if (i > 0) ir_fprintf(f, "\n");
ir_print_block_name(f, block);
ir_fprintf(f, ":\n");
for_array(j, block->instrs) {
irValue *value = block->instrs.e[j];
irValue *value = block->instrs[j];
ir_print_instr(f, m, value);
}
}
@@ -1555,7 +1555,7 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
}
for_array(i, proc->children) {
ir_print_proc(f, m, proc->children.e[i]);
ir_print_proc(f, m, proc->children[i]);
}
}
@@ -1573,7 +1573,7 @@ void ir_print_type_name(irFileBuffer *f, irModule *m, irValue *v) {
void print_llvm_ir(irGen *ir) {
irModule *m = &ir->module;
irFileBuffer buf = {0}, *f = &buf;
irFileBuffer buf = {}, *f = &buf;
ir_file_buffer_init(f, &ir->output_file);
ir_print_encoded_local(f, str_lit("..string"));
@@ -1606,7 +1606,7 @@ void print_llvm_ir(irGen *ir) {
for_array(member_index, m->members.entries) {
MapIrValueEntry *entry = &m->members.entries.e[member_index];
auto *entry = &m->members.entries[member_index];
irValue *v = entry->value;
if (v->kind != irValue_TypeName) {
continue;
@@ -1619,7 +1619,7 @@ void print_llvm_ir(irGen *ir) {
bool dll_main_found = false;
for_array(member_index, m->members.entries) {
MapIrValueEntry *entry = &m->members.entries.e[member_index];
auto *entry = &m->members.entries[member_index];
irValue *v = entry->value;
if (v->kind != irValue_Proc) {
continue;
@@ -1631,7 +1631,7 @@ void print_llvm_ir(irGen *ir) {
}
for_array(member_index, m->members.entries) {
MapIrValueEntry *entry = &m->members.entries.e[member_index];
auto *entry = &m->members.entries[member_index];
irValue *v = entry->value;
if (v->kind != irValue_Proc) {
continue;
@@ -1643,7 +1643,7 @@ void print_llvm_ir(irGen *ir) {
}
for_array(member_index, m->members.entries) {
MapIrValueEntry *entry = &m->members.entries.e[member_index];
auto *entry = &m->members.entries[member_index];
irValue *v = entry->value;
if (v->kind != irValue_Global) {
continue;
@@ -1707,13 +1707,13 @@ void print_llvm_ir(irGen *ir) {
ir_fprintf(f, "!%d = !{!\"clang version 3.9.0 (branches/release_39)\"}\n", diec+3);
for_array(di_index, m->debug_info.entries) {
MapIrDebugInfoEntry *entry = &m->debug_info.entries.e[di_index];
MapIrDebugInfoEntry *entry = &m->debug_info.entries[di_index];
irDebugInfo *di = entry->value;
ir_fprintf(f, "!%d = ", di->id);
switch (di->kind) {
case irDebugInfo_CompileUnit: {
irDebugInfo *file = *map_ir_debug_info_get(&m->debug_info, hash_pointer(di->CompileUnit.file));
irDebugInfo *file = *map_get(&m->debug_info, hash_pointer(di->CompileUnit.file));
ir_fprintf(f,
"distinct !DICompileUnit("
"language: DW_LANG_Go, " // Is this good enough?
@@ -1752,7 +1752,7 @@ void print_llvm_ir(irGen *ir) {
case irDebugInfo_AllProcs:
ir_fprintf(f, "!{");
for_array(proc_index, di->AllProcs.procs) {
irDebugInfo *p = di->AllProcs.procs.e[proc_index];
irDebugInfo *p = di->AllProcs.procs[proc_index];
if (proc_index > 0) {ir_fprintf(f, ",");}
ir_fprintf(f, "!%d", p->id);
}
+17 -26
View File
@@ -1,20 +1,15 @@
#if defined(__cplusplus)
extern "C" {
#endif
#define USE_CUSTOM_BACKEND false
#include "common.c"
#include "timings.c"
#include "build_settings.c"
#include "tokenizer.c"
#include "parser.c"
#include "checker.c"
#include "ssa.c"
#include "ir.c"
#include "ir_opt.c"
#include "ir_print.c"
// #include "vm.c"
#include "common.cpp"
#include "timings.cpp"
#include "build_settings.cpp"
#include "tokenizer.cpp"
#include "parser.cpp"
#include "checker.cpp"
#include "ssa.cpp"
#include "ir.cpp"
#include "ir_opt.cpp"
#include "ir_print.cpp"
#if defined(GB_SYSTEM_WINDOWS)
// NOTE(bill): `name` is used in debugging and profiling modes
@@ -155,27 +150,27 @@ int main(int argc, char **argv) {
char *init_filename = NULL;
bool run_output = false;
String arg1 = make_string_c(argv[1]);
if (str_eq(arg1, str_lit("run"))) {
if (arg1 == "run") {
if (argc != 3) {
usage(argv[0]);
return 1;
}
init_filename = argv[2];
run_output = true;
} else if (str_eq(arg1, str_lit("build_dll"))) {
} else if (arg1 == "build_dll") {
if (argc != 3) {
usage(argv[0]);
return 1;
}
init_filename = argv[2];
build_context.is_dll = true;
} else if (str_eq(arg1, str_lit("build"))) {
} else if (arg1 == "build") {
if (argc != 3) {
usage(argv[0]);
return 1;
}
init_filename = argv[2];
} else if (str_eq(arg1, str_lit("version"))) {
} else if (arg1 == "version") {
gb_printf("%s version %.*s\n", argv[0], LIT(build_context.ODIN_VERSION));
return 0;
} else {
@@ -314,7 +309,7 @@ int main(int argc, char **argv) {
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {0};
for_array(i, ir_gen.module.foreign_library_paths) {
String lib = ir_gen.module.foreign_library_paths.e[i];
String lib = ir_gen.module.foreign_library_paths[i];
// gb_printf_err("Linking lib: %.*s\n", LIT(lib));
isize len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" \"%.*s\"", LIT(lib));
@@ -376,14 +371,14 @@ int main(int argc, char **argv) {
// defer (gb_string_free(lib_str));
char lib_str_buf[1024] = {0};
for_array(i, ir_gen.module.foreign_library_paths) {
String lib = ir_gen.module.foreign_library_paths.e[i];
String lib = ir_gen.module.foreign_library_paths[i];
// NOTE(zangent): Sometimes, you have to use -framework on MacOS.
// This allows you to specify '-f' in a #foreign_system_library,
// without having to implement any new syntax specifically for MacOS.
#if defined(GB_SYSTEM_OSX)
isize len;
if(lib.len > 2 && lib.text[0] == '-' && lib.text[1] == 'f') {
if(lib.len > 2 && lib[0] == '-' && lib[1] == 'f') {
len = gb_snprintf(lib_str_buf, gb_size_of(lib_str_buf),
" -framework %.*s ", (int)(lib.len) - 2, lib.text + 2);
} else {
@@ -461,7 +456,3 @@ int main(int argc, char **argv) {
return 0;
}
#if defined(__cplusplus)
}
#endif
-364
View File
@@ -1,364 +0,0 @@
/*
Example of usage:
#define MAP_TYPE String
#define MAP_PROC map_string_
#define MAP_NAME MapString
#include "map.c"
*/
// A `Map` is an unordered hash table which can allow for a key to point to multiple values
// with the use of the `multi_*` procedures.
// TODO(bill): I should probably allow the `multi_*` stuff to be #ifdefed out
#ifndef MAP_UTIL_STUFF
#define MAP_UTIL_STUFF
// NOTE(bill): This util stuff is the same for every `Map`
typedef struct MapFindResult {
isize hash_index;
isize entry_prev;
isize entry_index;
} MapFindResult;
typedef enum HashKeyKind {
HashKey_Default,
HashKey_String,
HashKey_Pointer,
} HashKeyKind;
typedef struct HashKey {
HashKeyKind kind;
u64 key;
union {
String string; // if String, s.len > 0
void * ptr;
};
} HashKey;
gb_inline HashKey hashing_proc(void const *data, isize len) {
HashKey h = {HashKey_Default};
h.kind = HashKey_Default;
// h.key = gb_murmur64(data, len);
h.key = gb_fnv64a(data, len);
// h.key = MurmurHash3_128(data, len, 0x3803cb8e);
return h;
}
gb_inline HashKey hash_string(String s) {
HashKey h = hashing_proc(s.text, s.len);
h.kind = HashKey_String;
h.string = s;
return h;
}
gb_inline HashKey hash_pointer(void *ptr) {
HashKey h = {HashKey_Default};
// h.key = u128_from_u64(cast(u64)cast(uintptr)ptr);
h.key = cast(u64)cast(uintptr)ptr;
h.ptr = ptr;
h.kind = HashKey_Default;
return h;
}
bool hash_key_equal(HashKey a, HashKey b) {
if (a.key == b.key) {
// NOTE(bill): If two string's hashes collide, compare the strings themselves
if (a.kind == HashKey_String) {
if (b.kind == HashKey_String) {
return str_eq(a.string, b.string);
}
return false;
}
return true;
}
return false;
}
#endif
#define _J2_IND(a, b) a##b
#define _J2(a, b) _J2_IND(a, b)
/*
MAP_TYPE - Entry type
MAP_PROC - Function prefix (e.g. entity_map_)
MAP_NAME - Name of Map (e.g. EntityMap)
*/
#define MAP_ENTRY _J2(MAP_NAME,Entry)
typedef struct MAP_ENTRY {
HashKey key;
isize next;
MAP_TYPE value;
} MAP_ENTRY;
typedef struct MAP_NAME {
Array(isize) hashes;
Array(MAP_ENTRY) entries;
} MAP_NAME;
void _J2(MAP_PROC,init) (MAP_NAME *h, gbAllocator a);
void _J2(MAP_PROC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity);
void _J2(MAP_PROC,destroy) (MAP_NAME *h);
MAP_TYPE *_J2(MAP_PROC,get) (MAP_NAME *h, HashKey key);
void _J2(MAP_PROC,set) (MAP_NAME *h, HashKey key, MAP_TYPE value);
void _J2(MAP_PROC,remove) (MAP_NAME *h, HashKey key);
void _J2(MAP_PROC,clear) (MAP_NAME *h);
void _J2(MAP_PROC,grow) (MAP_NAME *h);
void _J2(MAP_PROC,rehash) (MAP_NAME *h, isize new_count);
// Mutlivalued map procedure
MAP_ENTRY *_J2(MAP_PROC,multi_find_first)(MAP_NAME *h, HashKey key);
MAP_ENTRY *_J2(MAP_PROC,multi_find_next) (MAP_NAME *h, MAP_ENTRY *e);
isize _J2(MAP_PROC,multi_count) (MAP_NAME *h, HashKey key);
void _J2(MAP_PROC,multi_get_all) (MAP_NAME *h, HashKey key, MAP_TYPE *items);
void _J2(MAP_PROC,multi_insert) (MAP_NAME *h, HashKey key, MAP_TYPE value);
void _J2(MAP_PROC,multi_remove) (MAP_NAME *h, HashKey key, MAP_ENTRY *e);
void _J2(MAP_PROC,multi_remove_all)(MAP_NAME *h, HashKey key);
gb_inline void _J2(MAP_PROC,init)(MAP_NAME *h, gbAllocator a) {
array_init(&h->hashes, a);
array_init(&h->entries, a);
}
gb_inline void _J2(MAP_PROC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity) {
array_init_reserve(&h->hashes, a, capacity);
array_init_reserve(&h->entries, a, capacity);
}
gb_inline void _J2(MAP_PROC,destroy)(MAP_NAME *h) {
array_free(&h->entries);
array_free(&h->hashes);
}
gb_internal isize _J2(MAP_PROC,_add_entry)(MAP_NAME *h, HashKey key) {
MAP_ENTRY e = {0};
e.key = key;
e.next = -1;
array_add(&h->entries, e);
return h->entries.count-1;
}
gb_internal MapFindResult _J2(MAP_PROC,_find)(MAP_NAME *h, HashKey key) {
MapFindResult fr = {-1, -1, -1};
if (h->hashes.count > 0) {
fr.hash_index = key.key % h->hashes.count;
fr.entry_index = h->hashes.e[fr.hash_index];
while (fr.entry_index >= 0) {
if (hash_key_equal(h->entries.e[fr.entry_index].key, key)) {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = h->entries.e[fr.entry_index].next;
}
}
return fr;
}
gb_internal MapFindResult _J2(MAP_PROC,_find_from_entry)(MAP_NAME *h, MAP_ENTRY *e) {
MapFindResult fr = {-1, -1, -1};
if (h->hashes.count > 0) {
fr.hash_index = e->key.key % h->hashes.count;
fr.entry_index = h->hashes.e[fr.hash_index];
while (fr.entry_index >= 0) {
if (&h->entries.e[fr.entry_index] == e) {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = h->entries.e[fr.entry_index].next;
}
}
return fr;
}
gb_internal b32 _J2(MAP_PROC,_full)(MAP_NAME *h) {
return 0.75f * h->hashes.count <= h->entries.count;
}
gb_inline void _J2(MAP_PROC,grow)(MAP_NAME *h) {
isize new_count = ARRAY_GROW_FORMULA(h->entries.count);
_J2(MAP_PROC,rehash)(h, new_count);
}
void _J2(MAP_PROC,rehash)(MAP_NAME *h, isize new_count) {
isize i, j;
MAP_NAME nh = {0};
_J2(MAP_PROC,init)(&nh, h->hashes.allocator);
array_resize(&nh.hashes, new_count);
array_reserve(&nh.entries, h->entries.count);
for (i = 0; i < new_count; i++) {
nh.hashes.e[i] = -1;
}
for (i = 0; i < h->entries.count; i++) {
MAP_ENTRY *e = &h->entries.e[i];
MapFindResult fr;
if (nh.hashes.count == 0) {
_J2(MAP_PROC,grow)(&nh);
}
fr = _J2(MAP_PROC,_find)(&nh, e->key);
j = _J2(MAP_PROC,_add_entry)(&nh, e->key);
if (fr.entry_prev < 0) {
nh.hashes.e[fr.hash_index] = j;
} else {
nh.entries.e[fr.entry_prev].next = j;
}
nh.entries.e[j].next = fr.entry_index;
nh.entries.e[j].value = e->value;
if (_J2(MAP_PROC,_full)(&nh)) {
_J2(MAP_PROC,grow)(&nh);
}
}
_J2(MAP_PROC,destroy)(h);
*h = nh;
}
gb_inline MAP_TYPE *_J2(MAP_PROC,get)(MAP_NAME *h, HashKey key) {
isize index = _J2(MAP_PROC,_find)(h, key).entry_index;
if (index >= 0) {
return &h->entries.e[index].value;
}
return NULL;
}
void _J2(MAP_PROC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
isize index;
MapFindResult fr;
if (h->hashes.count == 0)
_J2(MAP_PROC,grow)(h);
fr = _J2(MAP_PROC,_find)(h, key);
if (fr.entry_index >= 0) {
index = fr.entry_index;
} else {
index = _J2(MAP_PROC,_add_entry)(h, key);
if (fr.entry_prev >= 0) {
h->entries.e[fr.entry_prev].next = index;
} else {
h->hashes.e[fr.hash_index] = index;
}
}
h->entries.e[index].value = value;
if (_J2(MAP_PROC,_full)(h)) {
_J2(MAP_PROC,grow)(h);
}
}
void _J2(MAP_PROC,_erase)(MAP_NAME *h, MapFindResult fr) {
MapFindResult last;
if (fr.entry_prev < 0) {
h->hashes.e[fr.hash_index] = h->entries.e[fr.entry_index].next;
} else {
h->entries.e[fr.entry_prev].next = h->entries.e[fr.entry_index].next;
}
if (fr.entry_index == h->entries.count-1) {
array_pop(&h->entries);
return;
}
h->entries.e[fr.entry_index] = h->entries.e[h->entries.count-1];
last = _J2(MAP_PROC,_find)(h, h->entries.e[fr.entry_index].key);
if (last.entry_prev >= 0) {
h->entries.e[last.entry_prev].next = fr.entry_index;
} else {
h->hashes.e[last.hash_index] = fr.entry_index;
}
}
void _J2(MAP_PROC,remove)(MAP_NAME *h, HashKey key) {
MapFindResult fr = _J2(MAP_PROC,_find)(h, key);
if (fr.entry_index >= 0) {
_J2(MAP_PROC,_erase)(h, fr);
}
}
gb_inline void _J2(MAP_PROC,clear)(MAP_NAME *h) {
array_clear(&h->hashes);
array_clear(&h->entries);
}
#if 1
MAP_ENTRY *_J2(MAP_PROC,multi_find_first)(MAP_NAME *h, HashKey key) {
isize i = _J2(MAP_PROC,_find)(h, key).entry_index;
if (i < 0) {
return NULL;
}
return &h->entries.e[i];
}
MAP_ENTRY *_J2(MAP_PROC,multi_find_next)(MAP_NAME *h, MAP_ENTRY *e) {
isize i = e->next;
while (i >= 0) {
if (hash_key_equal(h->entries.e[i].key, e->key)) {
return &h->entries.e[i];
}
i = h->entries.e[i].next;
}
return NULL;
}
isize _J2(MAP_PROC,multi_count)(MAP_NAME *h, HashKey key) {
isize count = 0;
MAP_ENTRY *e = _J2(MAP_PROC,multi_find_first)(h, key);
while (e != NULL) {
count++;
e = _J2(MAP_PROC,multi_find_next)(h, e);
}
return count;
}
void _J2(MAP_PROC,multi_get_all)(MAP_NAME *h, HashKey key, MAP_TYPE *items) {
isize i = 0;
MAP_ENTRY *e = _J2(MAP_PROC,multi_find_first)(h, key);
while (e != NULL) {
items[i++] = e->value;
e = _J2(MAP_PROC,multi_find_next)(h, e);
}
}
void _J2(MAP_PROC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
MapFindResult fr;
isize i;
if (h->hashes.count == 0) {
_J2(MAP_PROC,grow)(h);
}
// Make
fr = _J2(MAP_PROC,_find)(h, key);
i = _J2(MAP_PROC,_add_entry)(h, key);
if (fr.entry_prev < 0) {
h->hashes.e[fr.hash_index] = i;
} else {
h->entries.e[fr.entry_prev].next = i;
}
h->entries.e[i].next = fr.entry_index;
h->entries.e[i].value = value;
// Grow if needed
if (_J2(MAP_PROC,_full)(h)) {
_J2(MAP_PROC,grow)(h);
}
}
void _J2(MAP_PROC,multi_remove)(MAP_NAME *h, HashKey key, MAP_ENTRY *e) {
MapFindResult fr = _J2(MAP_PROC,_find_from_entry)(h, e);
if (fr.entry_index >= 0) {
_J2(MAP_PROC,_erase)(h, fr);
}
}
void _J2(MAP_PROC,multi_remove_all)(MAP_NAME *h, HashKey key) {
while (_J2(MAP_PROC,get)(h, key) != NULL) {
_J2(MAP_PROC,remove)(h, key);
}
}
#endif
#undef _J2
#undef MAP_TYPE
#undef MAP_PROC
#undef MAP_NAME
#undef MAP_ENTRY
+364
View File
@@ -0,0 +1,364 @@
// A `Map` is an unordered hash table which can allow for a key to point to multiple values
// with the use of the `multi_*` procedures.
// TODO(bill): I should probably allow the `multi_map_*` stuff to be #ifdefed out
#ifndef MAP_UTIL_STUFF
#define MAP_UTIL_STUFF
// NOTE(bill): This util stuff is the same for every `Map`
struct MapFindResult {
isize hash_index;
isize entry_prev;
isize entry_index;
};
enum HashKeyKind {
HashKey_Default,
HashKey_String,
HashKey_Pointer,
};
struct HashKey {
HashKeyKind kind;
// u128 key;
u64 key;
union {
String string; // if String, s.len > 0
void * ptr;
};
};
gb_inline HashKey hashing_proc(void const *data, isize len) {
HashKey h = {HashKey_Default};
h.kind = HashKey_Default;
// h.key = u128_from_u64(gb_fnv64a(data, len));
h.key = gb_fnv64a(data, len);
return h;
}
gb_inline HashKey hash_string(String s) {
HashKey h = hashing_proc(s.text, s.len);
h.kind = HashKey_String;
h.string = s;
return h;
}
gb_inline HashKey hash_pointer(void *ptr) {
HashKey h = {HashKey_Default};
// h.key = u128_from_u64(cast(u64)cast(uintptr)ptr);
h.key = cast(u64)cast(uintptr)ptr;
h.ptr = ptr;
h.kind = HashKey_Default;
return h;
}
bool hash_key_equal(HashKey a, HashKey b) {
if (a.key == b.key) {
// NOTE(bill): If two string's hashes collide, compare the strings themselves
if (a.kind == HashKey_String) {
if (b.kind == HashKey_String) {
return a.string == b.string;
}
return false;
}
return true;
}
return false;
}
bool operator==(HashKey a, HashKey b) { return hash_key_equal(a, b); }
bool operator!=(HashKey a, HashKey b) { return !hash_key_equal(a, b); }
#endif
template <typename T>
struct MapEntry {
HashKey key;
isize next;
T value;
};
template <typename T>
struct Map {
Array<isize> hashes;
Array<MapEntry<T> > entries;
};
template <typename T> void map_init (Map<T> *h, gbAllocator a);
template <typename T> void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity);
template <typename T> void map_destroy (Map<T> *h);
template <typename T> T * map_get (Map<T> *h, HashKey key);
template <typename T> void map_set (Map<T> *h, HashKey key, T const &value);
template <typename T> void map_remove (Map<T> *h, HashKey key);
template <typename T> void map_clear (Map<T> *h);
template <typename T> void map_grow (Map<T> *h);
template <typename T> void map_rehash (Map<T> *h, isize new_count);
// Mutlivalued map procedure
template <typename T> MapEntry<T> * multi_map_find_first(Map<T> *h, HashKey key);
template <typename T> MapEntry<T> * multi_map_find_next (Map<T> *h, MapEntry<T> *e);
template <typename T> isize multi_map_count (Map<T> *h, HashKey key);
template <typename T> void multi_map_get_all (Map<T> *h, HashKey key, T *items);
template <typename T> void multi_map_insert (Map<T> *h, HashKey key, T const &value);
template <typename T> void multi_map_remove (Map<T> *h, HashKey key, MapEntry<T> *e);
template <typename T> void multi_map_remove_all(Map<T> *h, HashKey key);
template <typename T>
gb_inline void map_init(Map<T> *h, gbAllocator a) {
array_init(&h->hashes, a);
array_init(&h->entries, a);
}
template <typename T>
gb_inline void map_init_with_reserve(Map<T> *h, gbAllocator a, isize capacity) {
array_init(&h->hashes, a, capacity);
array_init(&h->entries, a, capacity);
}
template <typename T>
gb_inline void map_destroy(Map<T> *h) {
array_free(&h->entries);
array_free(&h->hashes);
}
template <typename T>
gb_internal isize map__add_entry(Map<T> *h, HashKey key) {
MapEntry<T> e = {};
e.key = key;
e.next = -1;
array_add(&h->entries, e);
return h->entries.count-1;
}
template <typename T>
gb_internal MapFindResult map__find(Map<T> *h, HashKey key) {
MapFindResult fr = {-1, -1, -1};
if (h->hashes.count > 0) {
// fr.hash_index = u128_to_i64(key.key % u128_from_i64(h->hashes.count));
fr.hash_index = key.key % h->hashes.count;
fr.entry_index = h->hashes[fr.hash_index];
while (fr.entry_index >= 0) {
if (hash_key_equal(h->entries[fr.entry_index].key, key)) {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = h->entries[fr.entry_index].next;
}
}
return fr;
}
template <typename T>
gb_internal MapFindResult map__find_from_entry(Map<T> *h, MapEntry<T> *e) {
MapFindResult fr = {-1, -1, -1};
if (h->hashes.count > 0) {
fr.hash_index = e->key.key % h->hashes.count;
fr.entry_index = h->hashes[fr.hash_index];
while (fr.entry_index >= 0) {
if (&h->entries[fr.entry_index] == e) {
return fr;
}
fr.entry_prev = fr.entry_index;
fr.entry_index = h->entries[fr.entry_index].next;
}
}
return fr;
}
template <typename T>
gb_internal b32 map__full(Map<T> *h) {
return 0.75f * h->hashes.count <= h->entries.count;
}
template <typename T>
gb_inline void map_grow(Map<T> *h) {
isize new_count = ARRAY_GROW_FORMULA(h->entries.count);
map_rehash(h, new_count);
}
template <typename T>
void map_rehash(Map<T> *h, isize new_count) {
isize i, j;
Map<T> nh = {};
map_init(&nh, h->hashes.allocator);
array_resize(&nh.hashes, new_count);
array_reserve(&nh.entries, h->entries.count);
for (i = 0; i < new_count; i++) {
nh.hashes[i] = -1;
}
for (i = 0; i < h->entries.count; i++) {
MapEntry<T> *e = &h->entries[i];
MapFindResult fr;
if (nh.hashes.count == 0) {
map_grow(&nh);
}
fr = map__find(&nh, e->key);
j = map__add_entry(&nh, e->key);
if (fr.entry_prev < 0) {
nh.hashes[fr.hash_index] = j;
} else {
nh.entries[fr.entry_prev].next = j;
}
nh.entries[j].next = fr.entry_index;
nh.entries[j].value = e->value;
if (map__full(&nh)) {
map_grow(&nh);
}
}
map_destroy(h);
*h = nh;
}
template <typename T>
gb_inline T *map_get(Map<T> *h, HashKey key) {
isize index = map__find(h, key).entry_index;
if (index >= 0) {
return &h->entries[index].value;
}
return NULL;
}
template <typename T>
void map_set(Map<T> *h, HashKey key, T const &value) {
isize index;
MapFindResult fr;
if (h->hashes.count == 0)
map_grow(h);
fr = map__find(h, key);
if (fr.entry_index >= 0) {
index = fr.entry_index;
} else {
index = map__add_entry(h, key);
if (fr.entry_prev >= 0) {
h->entries[fr.entry_prev].next = index;
} else {
h->hashes[fr.hash_index] = index;
}
}
h->entries[index].value = value;
if (map__full(h)) {
map_grow(h);
}
}
template <typename T>
void map__erase(Map<T> *h, MapFindResult fr) {
MapFindResult last;
if (fr.entry_prev < 0) {
h->hashes[fr.hash_index] = h->entries[fr.entry_index].next;
} else {
h->entries[fr.entry_prev].next = h->entries[fr.entry_index].next;
}
if (fr.entry_index == h->entries.count-1) {
array_pop(&h->entries);
return;
}
h->entries[fr.entry_index] = h->entries[h->entries.count-1];
last = map__find(h, h->entries[fr.entry_index].key);
if (last.entry_prev >= 0) {
h->entries[last.entry_prev].next = fr.entry_index;
} else {
h->hashes[last.hash_index] = fr.entry_index;
}
}
template <typename T>
void map_remove(Map<T> *h, HashKey key) {
MapFindResult fr = map__find(h, key);
if (fr.entry_index >= 0) {
map__erase(h, fr);
}
}
template <typename T>
gb_inline void map_clear(Map<T> *h) {
array_clear(&h->hashes);
array_clear(&h->entries);
}
#if 1
template <typename T>
MapEntry<T> *multi_map_find_first(Map<T> *h, HashKey key) {
isize i = map__find(h, key).entry_index;
if (i < 0) {
return NULL;
}
return &h->entries[i];
}
template <typename T>
MapEntry<T> *multi_map_find_next(Map<T> *h, MapEntry<T> *e) {
isize i = e->next;
while (i >= 0) {
if (hash_key_equal(h->entries[i].key, e->key)) {
return &h->entries[i];
}
i = h->entries[i].next;
}
return NULL;
}
template <typename T>
isize multi_map_count(Map<T> *h, HashKey key) {
isize count = 0;
MapEntry<T> *e = multi_map_find_first(h, key);
while (e != NULL) {
count++;
e = multi_map_find_next(h, e);
}
return count;
}
template <typename T>
void multi_map_get_all(Map<T> *h, HashKey key, T *items) {
isize i = 0;
MapEntry<T> *e = multi_map_find_first(h, key);
while (e != NULL) {
items[i++] = e->value;
e = multi_map_find_next(h, e);
}
}
template <typename T>
void multi_map_insert(Map<T> *h, HashKey key, T const &value) {
MapFindResult fr;
isize i;
if (h->hashes.count == 0) {
map_grow(h);
}
// Make
fr = map__find(h, key);
i = map__add_entry(h, key);
if (fr.entry_prev < 0) {
h->hashes[fr.hash_index] = i;
} else {
h->entries[fr.entry_prev].next = i;
}
h->entries[i].next = fr.entry_index;
h->entries[i].value = value;
// Grow if needed
if (map__full(h)) {
map_grow(h);
}
}
template <typename T>
void multi_map_remove(Map<T> *h, HashKey key, MapEntry<T> *e) {
MapFindResult fr = map__find_from_entry(h, e);
if (fr.entry_index >= 0) {
map__erase(h, fr);
}
}
template <typename T>
void multi_map_remove_all(Map<T> *h, HashKey key) {
while (map_get(h, key) != NULL) {
map_remove(h, key);
}
}
#endif
+22 -17
View File
@@ -41,15 +41,15 @@ gb_inline u64 fmix64(u64 k) {
return k;
}
gb_inline u32 mm3_getblock32(u32 *const p, isize i) {
gb_inline u32 mm3_getblock32(u32 const *p, isize i) {
return p[i];
}
gb_inline u64 mm3_getblock64(u64 *const p, isize i) {
gb_inline u64 mm3_getblock64(u64 const *p, isize i) {
return p[i];
}
u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
u8 *const data = cast(u8 *const)key;
void MurmurHash3_x64_128(void const *key, isize len, u32 seed, void *out) {
u8 const * data = cast(u8 const *)key;
isize nblocks = len / 16;
u64 h1 = seed;
@@ -58,7 +58,7 @@ u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
u64 const c1 = 0x87c37b91114253d5ULL;
u64 const c2 = 0x4cf5ad432745937fULL;
u64 *const blocks = cast(u64 *const)data;
u64 const * blocks = cast(u64 const *)data;
for (isize i = 0; i < nblocks; i++) {
u64 k1 = mm3_getblock64(blocks, i*2 + 0);
@@ -70,7 +70,7 @@ u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
}
u8 *const tail = cast(u8 *const)(data + nblocks*16);
u8 const * tail = cast(u8 const *)(data + nblocks*16);
u64 k1 = 0;
u64 k2 = 0;
@@ -108,11 +108,12 @@ u128 MurmurHash3_x64_128(void *const key, isize len, u32 seed) {
h1 += h2;
h2 += h1;
return u128_lo_hi(h1, h2);
((u64 *)out)[0] = h1;
((u64 *)out)[1] = h2;
}
u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
u8 *const data = cast(u8 * const)key;
void MurmurHash3_x86_128(void const *key, isize len, u32 seed, void *out) {
u8 const * data = cast(u8 * const)key;
isize nblocks = len / 16;
u32 h1 = seed;
@@ -128,7 +129,7 @@ u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
//----------
// body
u32 *const blocks = cast(u32 *const)(data + nblocks*16);
u32 const * blocks = cast(u32 const *)(data + nblocks*16);
for (isize i = -nblocks; i != 0; i++) {
u32 k1 = mm3_getblock32(blocks, i*4 + 0);
@@ -156,7 +157,7 @@ u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
//----------
// tail
u8 *const tail = cast(u8 *const)(data + nblocks*16);
u8 const * tail = cast(u8 const *)(data + nblocks*16);
u32 k1 = 0;
u32 k2 = 0;
@@ -204,17 +205,21 @@ u128 MurmurHash3_x86_128(void *const key, isize len, u32 seed) {
h1 += h2; h1 += h3; h1 += h4;
h2 += h1; h3 += h1; h4 += h1;
u64 lo = (u64)h1 | ((u64)h2 << 32);
u64 hi = (u64)h3 | ((u64)h4 << 32);
return u128_lo_hi(lo, hi);
((u32 *)out)[0] = h1;
((u32 *)out)[1] = h2;
((u32 *)out)[2] = h3;
((u32 *)out)[3] = h4;
}
gb_inline u128 MurmurHash3_128(void *const key, isize len, u32 seed) {
gb_inline u128 MurmurHash3_128(void const *key, isize len, u32 seed) {
u128 res;
#if defined(GB_ARCH_64_BIT)
return MurmurHash3_x64_128(key, len, seed);
MurmurHash3_x64_128(key, len, seed, &res);
#else
return MurmurHash3_x86_128(key, len, seed);
MurmurHash3_x86_128(key, len, seed, &res);
#endif
return res;
}
File diff suppressed because it is too large Load Diff
View File
+110 -109
View File
@@ -1,27 +1,21 @@
typedef struct ssaModule ssaModule;
typedef struct ssaValue ssaValue;
typedef struct ssaValueArgs ssaValueArgs;
typedef struct ssaDefer ssaDefer;
typedef struct ssaBlock ssaBlock;
typedef struct ssaProc ssaProc;
typedef struct ssaEdge ssaEdge;
typedef struct ssaRegister ssaRegister;
typedef struct ssaTargetList ssaTargetList;
typedef enum ssaBlockKind ssaBlockKind;
typedef enum ssaBranchPrediction ssaBranchPrediction;
typedef enum ssaDeferExitKind ssaDeferExitKind;
struct ssaModule;
struct ssaValue;
struct ssaValueArgs;
struct ssaDefer;
struct ssaBlock;
struct ssaProc;
struct ssaEdge;
struct ssaRegister;
struct ssaTargetList;
enum ssaBlockKind;
enum ssaBranchPrediction;
enum ssaDeferExitKind;
String ssa_mangle_name(ssaModule *m, String path, Entity *e);
#define MAP_TYPE ssaValue *
#define MAP_PROC map_ssa_value_
#define MAP_NAME MapSsaValue
#include "map.c"
typedef Array(ssaValue *) ssaValueArray;
#include "ssa_op.c"
#include "ssa_op.cpp"
#define SSA_DEFAULT_VALUE_ARG_CAPACITY 8
struct ssaValueArgs {
@@ -30,6 +24,15 @@ struct ssaValueArgs {
isize capacity;
ssaValue * backing[SSA_DEFAULT_VALUE_ARG_CAPACITY];
gbAllocator allocator;
ssaValue *&operator[](isize i) {
GB_ASSERT(0 <= i && i <= count);
return e[i];
}
ssaValue * const &operator[](isize i) const {
GB_ASSERT(0 <= i && i <= count);
return e[i];
}
};
struct ssaValue {
@@ -67,10 +70,10 @@ enum ssaBranchPrediction {
ssaBranch_Unlikely = -1,
};
typedef enum ssaDeferKind {
enum ssaDeferKind {
ssaDefer_Node,
ssaDefer_Instr,
} ssaDeferKind;
};
struct ssaDefer {
ssaDeferKind kind;
@@ -97,8 +100,6 @@ struct ssaEdge {
isize index;
};
typedef Array(ssaEdge) ssaEdgeArray;
struct ssaBlock {
i32 id; // Unique identifier but the pointer could be used too
ssaBlockKind kind;
@@ -115,9 +116,9 @@ struct ssaBlock {
// - BlockExit will be a memory control value
ssaValue *control;
ssaValueArray values;
ssaEdgeArray preds;
ssaEdgeArray succs;
Array<ssaValue *> values;
Array<ssaEdge> preds;
Array<ssaEdge> succs;
};
struct ssaTargetList {
@@ -134,7 +135,7 @@ struct ssaProc {
Entity * entity;
DeclInfo * decl_info;
Array(ssaBlock *) blocks;
Array<ssaBlock *> blocks;
ssaBlock * entry; // Entry block
ssaBlock * exit; // Exit block
ssaBlock * curr_block;
@@ -143,9 +144,9 @@ struct ssaProc {
i32 block_id;
i32 value_id;
MapSsaValue values; // Key: Entity *
Map<ssaValue *> values; // Key: Entity *
Array(ssaDefer) defer_stmts;
Array<ssaDefer> defer_stmts;
i32 scope_level;
};
@@ -161,10 +162,10 @@ struct ssaModule {
gbAllocator tmp_allocator;
gbArena tmp_arena;
MapEntity min_dep_map; // Key: Entity *
MapSsaValue values; // Key: Entity *
Map<Entity *> min_dep_map; // Key: Entity *
Map<ssaValue *> values; // Key: Entity *
// List of registers for the specific architecture
Array(ssaRegister) registers;
Array<ssaRegister> registers;
ssaProc *proc; // current procedure
@@ -172,19 +173,19 @@ struct ssaModule {
u32 stmt_state_flags;
Array(ssaProc *) procs;
ssaValueArray procs_to_generate;
Array<ssaProc *> procs;
Array<ssaValue *> procs_to_generate;
};
typedef enum ssaAddrKind {
enum ssaAddrKind {
ssaAddr_Default,
ssaAddr_Map,
} ssaAddrKind;
};
typedef struct ssaAddr {
struct ssaAddr {
ssaValue * addr;
ssaAddrKind kind;
} ssaAddr;
};
@@ -287,7 +288,7 @@ void ssa_add_arg(ssaValueArgs *va, ssaValue *arg) {
} else {
isize old_cap_size = va->capacity * gb_size_of(ssaValue *);
isize new_cap_size = capacity * gb_size_of(ssaValue *);
va->e = gb_resize(va->allocator, va->e, old_cap_size, new_cap_size);
*(cast(void **)&va->e) = gb_resize(va->allocator, va->e, old_cap_size, new_cap_size);
}
va->capacity = capacity;
}
@@ -378,9 +379,9 @@ ssaValue *ssa_const_i64 (ssaProc *p, Type *t, i64 c) { return ssa
ssaValue *ssa_const_f32 (ssaProc *p, Type *t, f32 c) { return ssa_const_val(p, ssaOp_Const32F, t, exact_value_float(c)); }
ssaValue *ssa_const_f64 (ssaProc *p, Type *t, f64 c) { return ssa_const_val(p, ssaOp_Const64F, t, exact_value_float(c)); }
ssaValue *ssa_const_string (ssaProc *p, Type *t, String c) { return ssa_const_val(p, ssaOp_ConstString, t, exact_value_string(c)); }
ssaValue *ssa_const_empty_string(ssaProc *p, Type *t) { return ssa_const_val(p, ssaOp_ConstString, t, (ExactValue){0}); }
ssaValue *ssa_const_empty_string(ssaProc *p, Type *t) { return ssa_const_val(p, ssaOp_ConstString, t, empty_exact_value); }
ssaValue *ssa_const_slice (ssaProc *p, Type *t, ExactValue v) { return ssa_const_val(p, ssaOp_ConstSlice, t, v); }
ssaValue *ssa_const_nil (ssaProc *p, Type *t) { return ssa_const_val(p, ssaOp_ConstNil, t, (ExactValue){0}); }
ssaValue *ssa_const_nil (ssaProc *p, Type *t) { return ssa_const_val(p, ssaOp_ConstNil, t, empty_exact_value); }
ssaValue *ssa_const_int(ssaProc *p, Type *t, i64 c) {
switch (8*type_size_of(p->allocator, t)) {
@@ -399,21 +400,21 @@ ssaValue *ssa_const_int(ssaProc *p, Type *t, i64 c) {
ssaAddr ssa_build_addr (ssaProc *p, AstNode *expr);
ssaValue *ssa_build_expr (ssaProc *p, AstNode *expr);
void ssa_build_stmt (ssaProc *p, AstNode *node);
void ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes);
void ssa_build_stmt_list(ssaProc *p, Array<AstNode *> nodes);
ssaValue *ssa_emit_deep_field_ptr_index(ssaProc *p, ssaValue *e, Selection sel);
void ssa_reset_value_args(ssaValue *v) {
for_array(i, v->args) {
v->args.e[i]->uses--;
v->args[i]->uses--;
}
v->args.count = 0;
}
void ssa_reset(ssaValue *v, ssaOp op) {
v->op = op;
v->exact_value = (ExactValue){0};
v->exact_value = empty_exact_value;
ssa_reset_value_args(v);
}
@@ -425,7 +426,7 @@ ssaValue *ssa_get_last_value(ssaBlock *b) {
if (len <= 0) {
return 0;
}
ssaValue *v = b->values.e[len-1];
ssaValue *v = b->values[len-1];
return v;
}
@@ -451,7 +452,7 @@ void ssa_build_defer_stmt(ssaProc *p, ssaDefer d) {
void ssa_emit_defer_stmts(ssaProc *p, ssaDeferExitKind kind, ssaBlock *b) {
isize count = p->defer_stmts.count;
for (isize i = count-1; i >= 0; i--) {
ssaDefer d = p->defer_stmts.e[i];
ssaDefer d = p->defer_stmts[i];
if (kind == ssaDeferExit_Default) {
gb_printf_err("scope_level %d %d\n", p->scope_level, d.scope_level);
if (p->scope_level == d.scope_level &&
@@ -579,7 +580,7 @@ ssaProc *ssa_new_proc(ssaModule *m, String name, Entity *entity, DeclInfo *decl_
array_init(&p->blocks, heap_allocator());
array_init(&p->defer_stmts, heap_allocator());
map_ssa_value_init(&p->values, heap_allocator());
map_init(&p->values, heap_allocator());
return p;
}
@@ -592,14 +593,14 @@ ssaAddr ssa_add_local(ssaProc *p, Entity *e, AstNode *expr) {
ssaValue *local = ssa_new_value0(p, ssaOp_Local, t);
p->curr_block = cb;
map_ssa_value_set(&p->values, hash_pointer(e), local);
map_ssa_value_set(&p->module->values, hash_pointer(e), local);
map_set(&p->values, hash_pointer(e), local);
map_set(&p->module->values, hash_pointer(e), local);
local->comment_string = e->token.string;
ssa_new_value1(p, ssaOp_Zero, t, local);
return ssa_addr(local);
}
ssaAddr ssa_add_local_for_ident(ssaProc *p, AstNode *name) {
Entity **found = map_entity_get(&p->module->info->definitions, hash_pointer(name));
Entity **found = map_get(&p->module->info->definitions, hash_pointer(name));
if (found) {
Entity *e = *found;
return ssa_add_local(p, e, name);
@@ -705,7 +706,7 @@ ssaValue *ssa_get_using_variable(ssaProc *p, Entity *e) {
Entity *parent = e->using_parent;
Selection sel = lookup_field(p->allocator, parent->type, name, false);
GB_ASSERT(sel.entity != NULL);
ssaValue **pv = map_ssa_value_get(&p->module->values, hash_pointer(parent));
ssaValue **pv = map_get(&p->module->values, hash_pointer(parent));
ssaValue *v = NULL;
if (pv != NULL) {
v = *pv;
@@ -721,7 +722,7 @@ ssaAddr ssa_build_addr_from_entity(ssaProc *p, Entity *e, AstNode *expr) {
GB_ASSERT(e != NULL);
ssaValue *v = NULL;
ssaValue **found = map_ssa_value_get(&p->module->values, hash_pointer(e));
ssaValue **found = map_get(&p->module->values, hash_pointer(e));
if (found) {
v = *found;
} else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) {
@@ -782,7 +783,7 @@ ssaValue *ssa_emit_conv(ssaProc *p, ssaValue *v, Type *t) {
// NOTE(bill): Returns NULL if not possible
ssaValue *ssa_address_from_load_or_generate_local(ssaProc *p, ssaValue *v) {
if (v->op == ssaOp_Load) {
return v->args.e[0];
return v->args[0];
}
ssaAddr addr = ssa_add_local_generated(p, v->type);
ssa_new_value2(p, ssaOp_Store, addr.addr->type, addr.addr, v);
@@ -863,7 +864,7 @@ ssaValue *ssa_emit_ptr_index(ssaProc *p, ssaValue *s, i64 index) {
ssaValue *ssa_emit_value_index(ssaProc *p, ssaValue *s, i64 index) {
if (s->op == ssaOp_Load) {
if (!can_ssa_type(s->type)) {
ssaValue *e = ssa_emit_ptr_index(p, s->args.e[0], index);
ssaValue *e = ssa_emit_ptr_index(p, s->args[0], index);
return ssa_emit_load(p, e);
}
}
@@ -930,7 +931,7 @@ ssaValue *ssa_emit_deep_field_ptr_index(ssaProc *p, ssaValue *e, Selection sel)
Type *type = type_deref(e->type);
for_array(i, sel.index) {
i32 index = cast(i32)sel.index.e[i];
i32 index = cast(i32)sel.index[i];
if (is_type_pointer(type)) {
type = type_deref(type);
e = ssa_emit_load(p, e);
@@ -994,14 +995,14 @@ ssaValue *ssa_emit_deep_field_value_index(ssaProc *p, ssaValue *e, Selection sel
Type *type = e->type;
if (e->op == ssaOp_Load) {
if (!can_ssa_type(e->type)) {
ssaValue *ptr = ssa_emit_deep_field_ptr_index(p, e->args.e[0], sel);
ssaValue *ptr = ssa_emit_deep_field_ptr_index(p, e->args[0], sel);
return ssa_emit_load(p, ptr);
}
}
GB_ASSERT(can_ssa_type(e->type));
for_array(i, sel.index) {
i32 index = cast(i32)sel.index.e[i];
i32 index = cast(i32)sel.index[i];
if (is_type_pointer(type)) {
e = ssa_emit_load(p, e);
}
@@ -1071,7 +1072,7 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) {
// GB_ASSERT(e->kind == Entity_Variable);
// GB_ASSERT(e->flags & EntityFlag_TypeField);
// String name = e->token.string;
// if (str_eq(name, str_lit("names"))) {
// if (name == "names") {
// ssaValue *ti_ptr = ir_type_info(p, type);
// ssaValue *names_ptr = NULL;
@@ -1685,7 +1686,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
case_end;
case_ast_node(i, Ident, expr);
Entity *e = *map_entity_get(&p->module->info->uses, hash_pointer(expr));
Entity *e = *map_get(&p->module->info->uses, hash_pointer(expr));
if (e->kind == Entity_Builtin) {
Token token = ast_node_token(expr);
GB_PANIC("TODO(bill): ssa_build_expr Entity_Builtin `%.*s`\n"
@@ -1697,7 +1698,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
return NULL;
}
ssaValue **found = map_ssa_value_get(&p->module->values, hash_pointer(e));
ssaValue **found = map_get(&p->module->values, hash_pointer(e));
if (found) {
ssaValue *v = *found;
if (v->op == ssaOp_Proc) {
@@ -1835,9 +1836,9 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
case_ast_node(ce, CallExpr, expr);
if (map_tav_get(&p->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
if (map_get(&p->module->info->types, hash_pointer(ce->proc))->mode == Addressing_Type) {
GB_ASSERT(ce->args.count == 1);
ssaValue *x = ssa_build_expr(p, ce->args.e[0]);
ssaValue *x = ssa_build_expr(p, ce->args[0]);
return ssa_emit_conv(p, x, tv.type);
}
@@ -1861,9 +1862,9 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) {
void ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes) {
void ssa_build_stmt_list(ssaProc *p, Array<AstNode *> nodes) {
for_array(i, nodes) {
ssa_build_stmt(p, nodes.e[i]);
ssa_build_stmt(p, nodes[i]);
}
}
@@ -1946,7 +1947,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
case_ast_node(us, UsingStmt, node);
for_array(i, us->list) {
AstNode *decl = unparen_expr(us->list.e[i]);
AstNode *decl = unparen_expr(us->list[i]);
if (decl->kind == AstNode_ValueDecl) {
ssa_build_stmt(p, decl);
}
@@ -1973,19 +1974,19 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
if (vd->values.count == 0) {
for_array(i, vd->names) {
AstNode *name = vd->names.e[i];
AstNode *name = vd->names[i];
if (!ssa_is_blank_ident(name)) {
ssa_add_local_for_ident(p, name);
}
}
} else {
Array(ssaAddr) lvals = {0};
ssaValueArray inits = {0};
array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
Array<ssaAddr> lvals = {0};
Array<ssaValue *> inits = {0};
array_init(&lvals, m->tmp_allocator, vd->names.count);
array_init(&inits, m->tmp_allocator, vd->names.count);
for_array(i, vd->names) {
AstNode *name = vd->names.e[i];
AstNode *name = vd->names[i];
ssaAddr lval = ssa_addr(NULL);
if (!ssa_is_blank_ident(name)) {
lval = ssa_add_local_for_ident(p, name);
@@ -1995,7 +1996,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
}
for_array(i, vd->values) {
ssaValue *init = ssa_build_expr(p, vd->values.e[i]);
ssaValue *init = ssa_build_expr(p, vd->values[i]);
if (init == NULL) { // TODO(bill): remove this
continue;
}
@@ -2012,7 +2013,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
}
for_array(i, inits) {
ssa_addr_store(p, lvals.e[i], inits.e[i]);
ssa_addr_store(p, lvals[i], inits[i]);
}
}
@@ -2030,11 +2031,11 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
switch (as->op.kind) {
case Token_Eq: {
Array(ssaAddr) lvals = {0};
Array<ssaAddr> lvals = {0};
array_init(&lvals, m->tmp_allocator);
for_array(i, as->lhs) {
AstNode *lhs = as->lhs.e[i];
AstNode *lhs = as->lhs[i];
ssaAddr lval = {0};
if (!ssa_is_blank_ident(lhs)) {
lval = ssa_build_addr(p, lhs);
@@ -2044,28 +2045,28 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
if (as->lhs.count == as->rhs.count) {
if (as->lhs.count == 1) {
AstNode *rhs = as->rhs.e[0];
AstNode *rhs = as->rhs[0];
ssaValue *init = ssa_build_expr(p, rhs);
ssa_addr_store(p, lvals.e[0], init);
ssa_addr_store(p, lvals[0], init);
} else {
ssaValueArray inits;
array_init_reserve(&inits, m->tmp_allocator, lvals.count);
Array<ssaValue *> inits;
array_init(&inits, m->tmp_allocator, lvals.count);
for_array(i, as->rhs) {
ssaValue *init = ssa_build_expr(p, as->rhs.e[i]);
ssaValue *init = ssa_build_expr(p, as->rhs[i]);
array_add(&inits, init);
}
for_array(i, inits) {
ssa_addr_store(p, lvals.e[i], inits.e[i]);
ssa_addr_store(p, lvals[i], inits[i]);
}
}
} else {
ssaValueArray inits;
array_init_reserve(&inits, m->tmp_allocator, lvals.count);
Array<ssaValue *> inits;
array_init(&inits, m->tmp_allocator, lvals.count);
for_array(i, as->rhs) {
ssaValue *init = ssa_build_expr(p, as->rhs.e[i]);
ssaValue *init = ssa_build_expr(p, as->rhs[i]);
Type *t = base_type(init->type);
// TODO(bill): refactor for code reuse as this is repeated a bit
if (t->kind == Type_Tuple) {
@@ -2080,7 +2081,7 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
}
for_array(i, inits) {
ssa_addr_store(p, lvals.e[i], inits.e[i]);
ssa_addr_store(p, lvals[i], inits[i]);
}
}
} break;
@@ -2091,8 +2092,8 @@ void ssa_build_stmt_internal(ssaProc *p, AstNode *node) {
// +=, -=, etc
i32 op = cast(i32)as->op.kind;
op += Token_Add - Token_AddEq; // Convert += to +
ssaAddr lhs = ssa_build_addr(p, as->lhs.e[0]);
ssaValue *value = ssa_build_expr(p, as->rhs.e[0]);
ssaAddr lhs = ssa_build_addr(p, as->lhs[0]);
ssaValue *value = ssa_build_expr(p, as->rhs[0]);
ssa_build_assign_op(p, lhs, value, cast(TokenKind)op);
} break;
}
@@ -2316,7 +2317,7 @@ void ssa_print_reg_value(gbFile *f, ssaValue *v) {
for_array(i, v->args) {
gb_fprintf(f, " ");
ssa_print_value(f, v->args.e[i]);
ssa_print_value(f, v->args[i]);
}
if (v->comment_string.len > 0) {
@@ -2335,12 +2336,12 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
bool *printed = gb_alloc_array(heap_allocator(), bool, p->value_id+1);
for_array(i, p->blocks) {
ssaBlock *b = p->blocks.e[i];
ssaBlock *b = p->blocks[i];
gb_fprintf(f, " b%d:", b->id);
if (b->preds.count > 0) {
gb_fprintf(f, " <-");
for_array(j, b->preds) {
ssaBlock *pred = b->preds.e[j].block;
ssaBlock *pred = b->preds[j].block;
gb_fprintf(f, " b%d", pred->id);
}
}
@@ -2351,7 +2352,7 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
isize n = 0;
for_array(j, b->values) {
ssaValue *v = b->values.e[j];
ssaValue *v = b->values[j];
if (v->op != ssaOp_Phi) {
continue;
}
@@ -2363,13 +2364,13 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
while (n < b->values.count) {
isize m = 0;
for_array(j, b->values) {
ssaValue *v = b->values.e[j];
ssaValue *v = b->values[j];
if (printed[v->id]) {
continue;
}
bool skip = false;
for_array(k, v->args) {
ssaValue *w = v->args.e[k];
ssaValue *w = v->args[k];
if (w != NULL && w->block == b && !printed[w->id]) {
skip = true;
break;
@@ -2387,7 +2388,7 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
if (m == n) {
gb_fprintf(f, "!!!!DepCycle!!!!\n");
for_array(k, b->values) {
ssaValue *v = b->values.e[k];
ssaValue *v = b->values[k];
if (printed[v->id]) {
continue;
}
@@ -2401,14 +2402,14 @@ void ssa_print_proc(gbFile *f, ssaProc *p) {
if (b->kind == ssaBlock_Plain) {
GB_ASSERT(b->succs.count == 1);
ssaBlock *next = b->succs.e[0].block;
ssaBlock *next = b->succs[0].block;
gb_fprintf(f, " ");
gb_fprintf(f, "jump b%d", next->id);
gb_fprintf(f, "\n");
} else if (b->kind == ssaBlock_If) {
GB_ASSERT(b->succs.count == 2);
ssaBlock *yes = b->succs.e[0].block;
ssaBlock *no = b->succs.e[1].block;
ssaBlock *yes = b->succs[0].block;
ssaBlock *no = b->succs[1].block;
gb_fprintf(f, " ");
gb_fprintf(f, "branch v%d, b%d, b%d", b->control->id, yes->id, no->id);
gb_fprintf(f, "\n");
@@ -2479,7 +2480,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
m.tmp_allocator = gb_arena_allocator(&m.tmp_arena);
m.allocator = gb_arena_allocator(&m.arena);
map_ssa_value_init(&m.values, heap_allocator());
map_init(&m.values, heap_allocator());
array_init(&m.registers, heap_allocator());
array_init(&m.procs, heap_allocator());
array_init(&m.procs_to_generate, heap_allocator());
@@ -2491,21 +2492,21 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
bool has_win_main = false;
for_array(i, info->entities.entries) {
MapDeclInfoEntry *entry = &info->entities.entries.e[i];
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
auto *entry = &info->entities.entries[i];
Entity *e = cast(Entity *)entry->key.ptr;
String name = e->token.string;
if (e->kind == Entity_Variable) {
global_variable_max_count++;
} else if (e->kind == Entity_Procedure && !e->scope->is_global) {
if (e->scope->is_init && str_eq(name, str_lit("main"))) {
if (e->scope->is_init && name == "main") {
entry_point = e;
}
if ((e->Procedure.tags & ProcTag_export) != 0 ||
(e->Procedure.link_name.len > 0) ||
(e->scope->is_file && e->Procedure.link_name.len > 0)) {
if (!has_dll_main && str_eq(name, str_lit("DllMain"))) {
if (!has_dll_main && name == "DllMain") {
has_dll_main = true;
} else if (!has_win_main && str_eq(name, str_lit("WinMain"))) {
} else if (!has_win_main && name == "WinMain") {
has_win_main = true;
}
}
@@ -2517,7 +2518,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
m.min_dep_map = generate_minimum_dependency_map(info, entry_point);
for_array(i, info->entities.entries) {
MapDeclInfoEntry *entry = &info->entities.entries.e[i];
auto *entry = &info->entities.entries[i];
Entity *e = cast(Entity *)entry->key.ptr;
String name = e->token.string;
DeclInfo *decl = entry->value;
@@ -2527,7 +2528,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
continue;
}
if (map_entity_get(&m.min_dep_map, hash_pointer(e)) == NULL) {
if (map_get(&m.min_dep_map, hash_pointer(e)) == NULL) {
// NOTE(bill): Nothing depends upon it so doesn't need to be built
continue;
}
@@ -2536,7 +2537,7 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
if (e->kind == Entity_Procedure && (e->Procedure.tags & ProcTag_export) != 0) {
} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
// Handle later
} else if (scope->is_init && e->kind == Entity_Procedure && str_eq(name, str_lit("main"))) {
} else if (scope->is_init && e->kind == Entity_Procedure && name == "main") {
} else {
name = ssa_mangle_name(&m, e->token.pos.file, e);
}
@@ -2574,8 +2575,8 @@ bool ssa_generate(Parser *parser, CheckerInfo *info) {
// ssa_module_add_value(m, e, p);
// HashKey hash_name = hash_string(name);
// if (map_ssa_value_get(&m.members, hash_name) == NULL) {
// map_ssa_value_set(&m.members, hash_name, p);
// if (map_get(&m.members, hash_name) == NULL) {
// map_set(&m.members, hash_name, p);
// }
} break;
}
@@ -2595,7 +2596,7 @@ String ssa_mangle_name(ssaModule *m, String path, Entity *e) {
String name = e->token.string;
CheckerInfo *info = m->info;
gbAllocator a = m->allocator;
AstFile *file = *map_ast_file_get(&info->files, hash_string(path));
AstFile *file = *map_get(&info->files, hash_string(path));
char *str = gb_alloc_array(a, char, path.len+1);
gb_memmove(str, path.text, path.len);
-1
View File
@@ -267,7 +267,6 @@ enum ssaOp {
SSA_OPS
#undef SSA_OP
};
typedef enum ssaOp ssaOp;
String const ssa_op_strings[] = {
#define SSA_OP(k) {cast(u8 *)#k, gb_size_of(#k)-1},
+66 -33
View File
@@ -1,5 +1,5 @@
gb_global gbArena string_buffer_arena = {0};
gb_global gbAllocator string_buffer_allocator = {0};
gb_global gbArena string_buffer_arena = {};
gb_global gbAllocator string_buffer_allocator = {};
void init_string_buffer_memory(void) {
// NOTE(bill): This should be enough memory for file systems
@@ -9,21 +9,38 @@ void init_string_buffer_memory(void) {
// NOTE(bill): Used for UTF-8 strings
typedef struct String {
struct String {
u8 * text;
isize len;
} String;
u8 &operator[](isize i) {
GB_ASSERT(0 <= i && i < len);
return text[i];
}
u8 const &operator[](isize i) const {
GB_ASSERT(0 <= i && i < len);
return text[i];
}
};
// NOTE(bill): used for printf style arguments
#define LIT(x) ((int)(x).len), (x).text
#define STR_LIT(c_str) {cast(u8 *)c_str, gb_size_of(c_str)-1}
#define str_lit(c_str) (String){cast(u8 *)c_str, gb_size_of(c_str)-1}
#define str_lit(c_str) String{cast(u8 *)c_str, gb_size_of(c_str)-1}
// NOTE(bill): String16 is only used for Windows due to its file directories
typedef struct String16 {
struct String16 {
wchar_t *text;
isize len;
} String16;
wchar_t &operator[](isize i) {
GB_ASSERT(0 <= i && i < len);
return text[i];
}
wchar_t const &operator[](isize i) const {
GB_ASSERT(0 <= i && i < len);
return text[i];
}
};
gb_inline String make_string(u8 *text, isize len) {
@@ -56,8 +73,8 @@ gb_inline bool str_eq_ignore_case(String a, String b) {
if (a.len == b.len) {
isize i;
for (i = 0; i < a.len; i++) {
char x = cast(char)a.text[i];
char y = cast(char)b.text[i];
char x = cast(char)a[i];
char y = cast(char)b[i];
if (gb_char_to_lower(x) != gb_char_to_lower(y))
return false;
}
@@ -88,16 +105,16 @@ int string_compare(String x, String y) {
for (; curr_block < fast; curr_block++) {
if (la[curr_block] ^ lb[curr_block]) {
for (pos = curr_block*gb_size_of(isize); pos < n; pos++) {
if (x.text[pos] ^ y.text[pos]) {
return cast(int)x.text[pos] - cast(int)y.text[pos];
if (x[pos] ^ y[pos]) {
return cast(int)x[pos] - cast(int)y[pos];
}
}
}
}
for (; offset < n; offset++) {
if (x.text[offset] ^ y.text[offset]) {
return cast(int)x.text[offset] - cast(int)y.text[offset];
if (x[offset] ^ y[offset]) {
return cast(int)x[offset] - cast(int)y[offset];
}
}
}
@@ -117,13 +134,29 @@ gb_inline bool str_gt(String a, String b) { return string_compare(a, b) > 0;
gb_inline bool str_le(String a, String b) { return string_compare(a, b) <= 0; }
gb_inline bool str_ge(String a, String b) { return string_compare(a, b) >= 0; }
bool operator == (String a, String b) { return str_eq(a, b); }
bool operator != (String a, String b) { return str_ne(a, b); }
bool operator < (String a, String b) { return str_lt(a, b); }
bool operator > (String a, String b) { return str_gt(a, b); }
bool operator <= (String a, String b) { return str_le(a, b); }
bool operator >= (String a, String b) { return str_ge(a, b); }
template <isize N> bool operator == (String a, char const (&b)[N]) { return str_eq(a, make_string(cast(u8 *)b, N-1)); }
template <isize N> bool operator != (String a, char const (&b)[N]) { return str_ne(a, make_string(cast(u8 *)b, N-1)); }
template <isize N> bool operator < (String a, char const (&b)[N]) { return str_lt(a, make_string(cast(u8 *)b, N-1)); }
template <isize N> bool operator > (String a, char const (&b)[N]) { return str_gt(a, make_string(cast(u8 *)b, N-1)); }
template <isize N> bool operator <= (String a, char const (&b)[N]) { return str_le(a, make_string(cast(u8 *)b, N-1)); }
template <isize N> bool operator >= (String a, char const (&b)[N]) { return str_ge(a, make_string(cast(u8 *)b, N-1)); }
gb_inline bool str_has_prefix(String s, String prefix) {
isize i;
if (prefix.len < s.len) {
return false;
}
for (i = 0; i < prefix.len; i++) {
if (s.text[i] != prefix.text[i]) {
if (s[i] != prefix[i]) {
return false;
}
}
@@ -135,9 +168,9 @@ gb_inline isize string_extension_position(String str) {
isize i = str.len;
bool seen_dot = false;
while (i --> 0) {
if (str.text[i] == GB_PATH_SEPARATOR)
if (str[i] == GB_PATH_SEPARATOR)
break;
if (str.text[i] == '.') {
if (str[i] == '.') {
dot_pos = i;
break;
}
@@ -147,11 +180,11 @@ gb_inline isize string_extension_position(String str) {
}
String string_trim_whitespace(String str) {
while (str.len > 0 && rune_is_whitespace(str.text[str.len-1])) {
while (str.len > 0 && rune_is_whitespace(str[str.len-1])) {
str.len--;
}
while (str.len > 0 && rune_is_whitespace(str.text[0])) {
while (str.len > 0 && rune_is_whitespace(str[0])) {
str.text++;
str.len--;
}
@@ -166,7 +199,7 @@ gb_inline bool string_has_extension(String str, String ext) {
}
isize len = str.len;
for (isize i = len-1; i >= 0; i--) {
if (str.text[i] == '.') {
if (str[i] == '.') {
break;
}
len--;
@@ -182,7 +215,7 @@ gb_inline bool string_has_extension(String str, String ext) {
bool string_contains_char(String s, u8 c) {
isize i;
for (i = 0; i < s.len; i++) {
if (s.text[i] == c)
if (s[i] == c)
return true;
}
return false;
@@ -194,8 +227,8 @@ String filename_from_path(String s) {
isize j = 0;
s.len = i;
for (j = i-1; j >= 0; j--) {
if (s.text[j] == '/' ||
s.text[j] == '\\') {
if (s[j] == '/' ||
s[j] == '\\') {
break;
}
}
@@ -315,18 +348,18 @@ 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;
if (s.text[0] == quote &&
if (s[0] == quote &&
(quote == '\'' || quote == '"')) {
return false;
} else if (s.text[0] >= 0x80) {
} else if (s[0] >= 0x80) {
Rune r = -1;
isize size = gb_utf8_decode(s.text, s.len, &r);
*rune = r;
*multiple_bytes = true;
*tail_string = make_string(s.text+size, s.len-size);
return true;
} else if (s.text[0] != '\\') {
*rune = s.text[0];
} else if (s[0] != '\\') {
*rune = s[0];
*tail_string = make_string(s.text+1, s.len-1);
return true;
}
@@ -334,7 +367,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
if (s.len <= 1) {
return false;
}
c = s.text[1];
c = s[1];
s = make_string(s.text+2, s.len-2);
switch (c) {
@@ -372,7 +405,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
return false;
}
for (i = 0; i < 2; i++) {
i32 d = gb_digit_to_int(s.text[i]);
i32 d = gb_digit_to_int(s[i]);
if (d < 0 || d > 7) {
return false;
}
@@ -400,7 +433,7 @@ bool unquote_char(String s, u8 quote, Rune *rune, bool *multiple_bytes, String *
return false;
}
for (i = 0; i < count; i++) {
i32 d = gb_hex_digit_to_int(s.text[i]);
i32 d = gb_hex_digit_to_int(s[i]);
if (d < 0) {
return false;
}
@@ -433,8 +466,8 @@ i32 unquote_string(gbAllocator a, String *s_) {
if (n < 2) {
return 0;
}
quote = s.text[0];
if (quote != s.text[n-1]) {
quote = s[0];
if (quote != s[n-1]) {
return 0;
}
s.text += 1;
@@ -471,12 +504,12 @@ i32 unquote_string(gbAllocator a, String *s_) {
{
u8 rune_temp[4] = {0};
u8 rune_temp[4] = {};
isize buf_len = 3*s.len / 2;
u8 *buf = gb_alloc_array(a, u8, buf_len);
isize offset = 0;
while (s.len > 0) {
String tail_string = {0};
String tail_string = {};
Rune r = 0;
bool multiple_bytes = false;
bool success = unquote_char(s, quote, &r, &multiple_bytes, &tail_string);
+10 -10
View File
@@ -1,14 +1,14 @@
typedef struct TimeStamp {
struct TimeStamp {
u64 start;
u64 finish;
String label;
} TimeStamp;
};
typedef struct Timings {
struct Timings {
TimeStamp total;
Array(TimeStamp) sections;
Array<TimeStamp> sections;
u64 freq;
} Timings;
};
#if defined(GB_SYSTEM_WINDOWS)
@@ -83,7 +83,7 @@ TimeStamp make_time_stamp(String label) {
}
void timings_init(Timings *t, String label, isize buffer_size) {
array_init_reserve(&t->sections, heap_allocator(), buffer_size);
array_init(&t->sections, heap_allocator(), buffer_size);
t->total = make_time_stamp(label);
t->freq = time_stamp__freq();
}
@@ -94,7 +94,7 @@ void timings_destroy(Timings *t) {
void timings__stop_current_section(Timings *t) {
if (t->sections.count > 0) {
t->sections.e[t->sections.count-1].finish = time_stamp_time_now();
t->sections[t->sections.count-1].finish = time_stamp_time_now();
}
}
@@ -110,14 +110,14 @@ f64 time_stamp_as_ms(TimeStamp ts, u64 freq) {
void timings_print_all(Timings *t) {
char const SPACES[] = " ";
isize max_len, i;
isize max_len;
timings__stop_current_section(t);
t->total.finish = time_stamp_time_now();
max_len = t->total.label.len;
for_array(i, t->sections) {
TimeStamp ts = t->sections.e[i];
TimeStamp ts = t->sections[i];
max_len = gb_max(max_len, ts.label.len);
}
@@ -129,7 +129,7 @@ void timings_print_all(Timings *t) {
time_stamp_as_ms(t->total, t->freq));
for_array(i, t->sections) {
TimeStamp ts = t->sections.e[i];
TimeStamp ts = t->sections[i];
gb_printf("%.*s%.*s - %.3f ms\n",
LIT(ts.label),
cast(int)(max_len-ts.label.len), SPACES,
+22 -22
View File
@@ -117,11 +117,11 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
TOKEN_KIND(Token__KeywordEnd, "_KeywordEnd"), \
TOKEN_KIND(Token_Count, "")
typedef enum TokenKind {
enum TokenKind {
#define TOKEN_KIND(e, s) e
TOKEN_KINDS
#undef TOKEN_KIND
} TokenKind;
};
String const token_strings[] = {
#define TOKEN_KIND(e, s) {cast(u8 *)s, gb_size_of(s)-1}
@@ -130,11 +130,11 @@ String const token_strings[] = {
};
typedef struct TokenPos {
struct TokenPos {
String file;
isize line;
isize column;
} TokenPos;
};
i32 token_pos_cmp(TokenPos a, TokenPos b) {
if (a.line == b.line) {
@@ -152,11 +152,11 @@ bool token_pos_eq(TokenPos a, TokenPos b) {
return token_pos_cmp(a, b) == 0;
}
typedef struct Token {
struct Token {
TokenKind kind;
String string;
TokenPos pos;
} Token;
};
Token empty_token = {Token_Invalid};
Token blank_token = {Token_Ident, {cast(u8 *)"_", 1}};
@@ -167,12 +167,12 @@ Token make_token_ident(String s) {
}
typedef struct ErrorCollector {
struct ErrorCollector {
TokenPos prev;
i64 count;
i64 warning_count;
gbMutex mutex;
} ErrorCollector;
};
gb_global ErrorCollector global_error_collector;
@@ -306,7 +306,7 @@ gb_inline bool token_is_shift(TokenKind t) {
gb_inline void print_token(Token t) { gb_printf("%.*s\n", LIT(t.string)); }
typedef enum TokenizerInitError {
enum TokenizerInitError {
TokenizerInit_None,
TokenizerInit_Invalid,
@@ -315,18 +315,18 @@ typedef enum TokenizerInitError {
TokenizerInit_Empty,
TokenizerInit_Count,
} TokenizerInitError;
};
typedef struct TokenizerState {
struct TokenizerState {
Rune curr_rune; // current character
u8 * curr; // character pos
u8 * read_curr; // pos from start
u8 * line; // current line pos
isize line_count;
} TokenizerState;
};
typedef struct Tokenizer {
struct Tokenizer {
String fullpath;
u8 *start;
u8 *end;
@@ -338,12 +338,12 @@ typedef struct Tokenizer {
isize line_count;
isize error_count;
Array(String) allocated_strings;
} Tokenizer;
Array<String> allocated_strings;
};
TokenizerState save_tokenizer_state(Tokenizer *t) {
TokenizerState state = {0};
TokenizerState state = {};
state.curr_rune = t->curr_rune;
state.curr = t->curr;
state.read_curr = t->read_curr;
@@ -435,7 +435,7 @@ TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
array_init(&t->allocated_strings, heap_allocator());
} else {
gbFile f = {0};
gbFile f = {};
gbFileError file_err = gb_file_open(&f, c_str);
switch (file_err) {
@@ -460,7 +460,7 @@ gb_inline void destroy_tokenizer(Tokenizer *t) {
gb_free(heap_allocator(), t->start);
}
for_array(i, t->allocated_strings) {
gb_free(heap_allocator(), t->allocated_strings.e[i].text);
gb_free(heap_allocator(), t->allocated_strings[i].text);
}
array_free(&t->allocated_strings);
}
@@ -492,7 +492,7 @@ gb_inline void scan_mantissa(Tokenizer *t, i32 base) {
}
Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
Token token = {0};
Token token = {};
token.kind = Token_Integer;
token.string = make_string(t->curr, 1);
token.pos.file = t->fullpath;
@@ -742,7 +742,7 @@ bool tokenizer_find_line_end(Tokenizer *t) {
Token tokenizer_get_token(Tokenizer *t) {
tokenizer_skip_whitespace(t);
Token token = {0};
Token token = {};
token.string = make_string(t->curr, 1);
token.pos.file = t->fullpath;
token.pos.line = t->line_count;
@@ -760,7 +760,7 @@ Token tokenizer_get_token(Tokenizer *t) {
// NOTE(bill): All keywords are > 1
if (token.string.len > 1) {
for (i32 k = Token__KeywordBegin+1; k < Token__KeywordEnd; k++) {
if (str_eq(token.string, token_strings[k])) {
if (token.string == token_strings[k]) {
token.kind = cast(TokenKind)k;
break;
}
@@ -963,7 +963,7 @@ Token tokenizer_get_token(Tokenizer *t) {
default:
if (curr_rune != GB_RUNE_BOM) {
u8 str[4] = {0};
u8 str[4] = {};
int len = cast(int)gb_utf8_encode_rune(str, curr_rune);
tokenizer_err(t, "Illegal character: %.*s (%d) ", len, str, curr_rune);
}
+55 -55
View File
@@ -1,6 +1,6 @@
typedef struct Scope Scope;
struct Scope;
typedef enum BasicKind {
enum BasicKind {
Basic_Invalid,
Basic_bool,
Basic_i8,
@@ -41,9 +41,9 @@ typedef enum BasicKind {
Basic_COUNT,
Basic_byte = Basic_u8,
} BasicKind;
};
typedef enum BasicFlag {
enum BasicFlag {
BasicFlag_Boolean = GB_BIT(0),
BasicFlag_Integer = GB_BIT(1),
BasicFlag_Unsigned = GB_BIT(2),
@@ -57,16 +57,16 @@ typedef enum BasicFlag {
BasicFlag_Numeric = BasicFlag_Integer | BasicFlag_Float | BasicFlag_Complex,
BasicFlag_Ordered = BasicFlag_Integer | BasicFlag_Float | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
BasicFlag_ConstantType = BasicFlag_Boolean | BasicFlag_Numeric | BasicFlag_String | BasicFlag_Pointer | BasicFlag_Rune,
} BasicFlag;
};
typedef struct BasicType {
struct BasicType {
BasicKind kind;
u32 flags;
i64 size; // -1 if arch. dep.
String name;
} BasicType;
};
typedef enum TypeRecordKind {
enum TypeRecordKind {
TypeRecord_Invalid,
TypeRecord_Struct,
@@ -75,9 +75,9 @@ typedef enum TypeRecordKind {
TypeRecord_Enum,
TypeRecord_Count,
} TypeRecordKind;
};
typedef struct TypeRecord {
struct TypeRecord {
TypeRecordKind kind;
// All record types
@@ -109,7 +109,7 @@ typedef struct TypeRecord {
Entity * enum_count;
Entity * enum_min_value;
Entity * enum_max_value;
} TypeRecord;
};
#define TYPE_KINDS \
TYPE_KIND(Basic, BasicType) \
@@ -164,13 +164,13 @@ typedef struct TypeRecord {
typedef enum TypeKind {
enum TypeKind {
Type_Invalid,
#define TYPE_KIND(k, ...) GB_JOIN2(Type_, k),
TYPE_KINDS
#undef TYPE_KIND
Type_Count,
} TypeKind;
};
String const type_strings[] = {
{cast(u8 *)"Invalid", gb_size_of("Invalid")},
@@ -183,7 +183,7 @@ String const type_strings[] = {
TYPE_KINDS
#undef TYPE_KIND
typedef struct Type {
struct Type {
TypeKind kind;
union {
#define TYPE_KIND(k, ...) GB_JOIN2(Type, k) k;
@@ -191,19 +191,19 @@ typedef struct Type {
#undef TYPE_KIND
};
bool failure;
} Type;
};
// TODO(bill): Should I add extra information here specifying the kind of selection?
// e.g. field, constant, vector field, type field, etc.
typedef struct Selection {
Entity * entity;
Array_i32 index;
bool indirect; // Set if there was a pointer deref anywhere down the line
} Selection;
struct Selection {
Entity * entity;
Array<i32> index;
bool indirect; // Set if there was a pointer deref anywhere down the line
};
Selection empty_selection = {0};
Selection make_selection(Entity *entity, Array_i32 index, bool indirect) {
Selection make_selection(Entity *entity, Array<i32> index, bool indirect) {
Selection s = {entity, index, indirect};
return s;
}
@@ -212,10 +212,10 @@ void selection_add_index(Selection *s, isize index) {
// IMPORTANT NOTE(bill): this requires a stretchy buffer/dynamic array so it requires some form
// of heap allocation
// TODO(bill): Find a way to use a backing buffer for initial use as the general case is probably .count<3
if (s->index.e == NULL) {
if (s->index.data == NULL) {
array_init(&s->index, heap_allocator());
}
array_add(&s->index, index);
array_add(&s->index, cast(i32)index);
}
@@ -1025,7 +1025,7 @@ bool are_types_identical(Type *x, Type *y) {
if (!are_types_identical(xf->type, yf->type)) {
return false;
}
if (str_ne(xf->token.string, yf->token.string)) {
if (xf->token.string != yf->token.string) {
return false;
}
bool xf_is_using = (xf->flags&EntityFlag_Using) != 0;
@@ -1039,7 +1039,7 @@ bool are_types_identical(Type *x, Type *y) {
if (!are_types_identical(x->Record.variants[i]->type, y->Record.variants[i]->type)) {
return false;
}
if (str_ne(x->Record.variants[i]->token.string, y->Record.variants[i]->token.string)) {
if (x->Record.variants[i]->token.string != y->Record.variants[i]->token.string) {
return false;
}
}
@@ -1199,7 +1199,7 @@ bool is_type_cte_safe(Type *type) {
return false;
}
typedef enum ProcTypeOverloadKind {
enum ProcTypeOverloadKind {
ProcOverload_Identical, // The types are identical
ProcOverload_CallingConvention,
@@ -1211,7 +1211,7 @@ typedef enum ProcTypeOverloadKind {
ProcOverload_NotProcedure,
} ProcTypeOverloadKind;
};
ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
if (x == NULL && y == NULL) return ProcOverload_NotProcedure;
@@ -1297,9 +1297,9 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
Entity *f = type->Record.fields[i];
if (f->kind == Entity_Variable) {
if (f->Variable.field_src_index == index) {
Array_i32 sel_array = {0};
Array<i32> sel_array = {0};
array_init_count(&sel_array, a, 1);
sel_array.e[0] = i;
sel_array[0] = i;
return make_selection(f, sel_array, false);
}
}
@@ -1309,18 +1309,18 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) {
for (isize i = 0; i < max_count; i++) {
Entity *f = type->Tuple.variables[i];
if (i == index) {
Array_i32 sel_array = {0};
Array<i32> sel_array = {0};
array_init_count(&sel_array, a, 1);
sel_array.e[0] = i;
sel_array[0] = i;
return make_selection(f, sel_array, false);
}
}
break;
case Type_BitField: {
Array_i32 sel_array = {0};
Array<i32> sel_array = {0};
array_init_count(&sel_array, a, 1);
sel_array.e[0] = cast(i32)index;
sel_array[0] = cast(i32)index;
return make_selection(type->BitField.fields[index], sel_array, false);
} break;
@@ -1337,7 +1337,7 @@ gb_global Entity *entity__any_type_info = NULL;
Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) {
GB_ASSERT(type_ != NULL);
if (str_eq(field_name, str_lit("_"))) {
if (field_name == "_") {
return empty_selection;
}
@@ -1362,11 +1362,11 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 1);
}
if (str_eq(field_name, data_str)) {
if (field_name == data_str) {
selection_add_index(&sel, 0);
sel.entity = entity__any_data;;
return sel;
} else if (str_eq(field_name, type_info_str)) {
} else if (field_name == type_info_str) {
selection_add_index(&sel, 1);
sel.entity = entity__any_type_info;
return sel;
@@ -1382,7 +1382,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
switch (type->Vector.count) {
#define _VECTOR_FIELD_CASE(_length, _name) \
case (_length): \
if (str_eq(field_name, str_lit(_name))) { \
if (field_name == _name) { \
selection_add_index(&sel, (_length)-1); \
sel.entity = make_entity_vector_elem(a, NULL, make_token_ident(str_lit(_name)), type->Vector.elem, (_length)-1); \
return sel; \
@@ -1403,7 +1403,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
if (is_type) {
if (type->kind == Type_Record) {
if (type->Record.names != NULL &&
str_eq(field_name, str_lit("names"))) {
field_name == "names") {
sel.entity = type->Record.names;
return sel;
}
@@ -1415,7 +1415,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
GB_ASSERT(f->kind == Entity_TypeName);
String str = f->token.string;
if (str_eq(str, field_name)) {
if (str == field_name) {
sel.entity = f;
// selection_add_index(&sel, i);
return sel;
@@ -1424,15 +1424,15 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
} else if (is_type_enum(type)) {
// NOTE(bill): These may not have been added yet, so check in case
if (type->Record.enum_count != NULL) {
if (str_eq(field_name, str_lit("count"))) {
if (field_name == "count") {
sel.entity = type->Record.enum_count;
return sel;
}
if (str_eq(field_name, str_lit("min_value"))) {
if (field_name == "min_value") {
sel.entity = type->Record.enum_min_value;
return sel;
}
if (str_eq(field_name, str_lit("max_value"))) {
if (field_name == "max_value") {
sel.entity = type->Record.enum_max_value;
return sel;
}
@@ -1443,7 +1443,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
GB_ASSERT(f->kind == Entity_Constant);
String str = f->token.string;
if (str_eq(field_name, str)) {
if (field_name == str) {
sel.entity = f;
// selection_add_index(&sel, i);
return sel;
@@ -1457,7 +1457,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
continue;
}
String str = f->token.string;
if (str_eq(field_name, str)) {
if (field_name == str) {
selection_add_index(&sel, i); // HACK(bill): Leaky memory
sel.entity = f;
return sel;
@@ -1479,7 +1479,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
}
}
if (type->Record.kind == TypeRecord_Union) {
if (str_eq(field_name, str_lit("__tag"))) {
if (field_name == "__tag") {
Entity *e = type->Record.union__tag;
GB_ASSERT(e != NULL);
selection_add_index(&sel, -1); // HACK(bill): Leaky memory
@@ -1496,7 +1496,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
}
String str = f->token.string;
if (str_eq(field_name, str)) {
if (field_name == str) {
selection_add_index(&sel, i); // HACK(bill): Leaky memory
sel.entity = f;
return sel;
@@ -1508,10 +1508,10 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
}
typedef struct TypePath {
Array(Type *) path; // Entity_TypeName;
struct TypePath {
Array<Type *> path; // Entity_TypeName;
bool failure;
} TypePath;
};
void type_path_init(TypePath *tp) {
// TODO(bill): Use an allocator that uses a backing array if it can and then use alternative allocator when exhausted
@@ -1526,7 +1526,7 @@ void type_path_print_illegal_cycle(TypePath *tp, isize start_index) {
GB_ASSERT(tp != NULL);
GB_ASSERT(start_index < tp->path.count);
Type *t = tp->path.e[start_index];
Type *t = tp->path[start_index];
GB_ASSERT(t != NULL);
GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
@@ -1534,7 +1534,7 @@ void type_path_print_illegal_cycle(TypePath *tp, isize start_index) {
error(e->token, "Illegal declaration cycle of `%.*s`", LIT(t->Named.name));
// NOTE(bill): Print cycle, if it's deep enough
for (isize j = start_index; j < tp->path.count; j++) {
Type *t = tp->path.e[j];
Type *t = tp->path[j];
GB_ASSERT_MSG(is_type_named(t), "%s", type_to_string(t));
Entity *e = t->Named.type_name;
error(e->token, "\t%.*s refers to", LIT(t->Named.name));
@@ -1549,7 +1549,7 @@ TypePath *type_path_push(TypePath *tp, Type *t) {
GB_ASSERT(tp != NULL);
for (isize i = 0; i < tp->path.count; i++) {
if (tp->path.e[i] == t) {
if (tp->path[i] == t) {
type_path_print_illegal_cycle(tp, i);
}
}
@@ -1617,7 +1617,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
switch (t->kind) {
case Type_Basic: {
GB_ASSERT(is_type_typed(t));
switch (t->kind) {
switch (t->Basic.kind) {
case Basic_string: return build_context.word_size;
case Basic_any: return build_context.word_size;
@@ -2082,7 +2082,7 @@ i64 type_offset_of_from_selection(gbAllocator allocator, Type *type, Selection s
Type *t = type;
i64 offset = 0;
for_array(i, sel.index) {
isize index = sel.index.e[i];
isize index = sel.index[i];
t = base_type(t);
offset += type_offset_of(allocator, t, index);
if (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct) {
@@ -2291,7 +2291,7 @@ gbString write_type_to_string(gbString str, Type *type) {
}
if (var->flags&EntityFlag_Ellipsis) {
Type *slice = base_type(var->type);
str = gb_string_appendc(str, "...");
str = gb_string_appendc(str, "..");
GB_ASSERT(is_type_slice(var->type));
str = write_type_to_string(str, slice->Slice.elem);
} else {
+2 -1
View File
@@ -1,9 +1,10 @@
#pragma warning(push)
#pragma warning(disable: 4245)
extern "C" {
// #include "utf8proc/utf8proc.h"
#include "utf8proc/utf8proc.c"
}
#pragma warning(pop)
+8 -12
View File
@@ -383,7 +383,7 @@ UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) {
}
UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) {
return utf8proc_get_property(c)->category;
return cast(utf8proc_category_t)utf8proc_get_property(c)->category;
}
UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
@@ -393,15 +393,15 @@ UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) {
#define utf8proc_decompose_lump(replacement_uc) \
return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
options & ~UTF8PROC_LUMP, last_boundclass)
(utf8proc_option_t)(options & ~UTF8PROC_LUMP), last_boundclass)
UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) {
const utf8proc_property_t *property;
utf8proc_propval_t category;
utf8proc_category_t category;
utf8proc_int32_t hangul_sindex;
if (uc < 0 || uc >= 0x110000) return UTF8PROC_ERROR_NOTASSIGNED;
property = unsafe_get_property(uc);
category = property->category;
category = cast(utf8proc_category_t)property->category;
hangul_sindex = uc - UTF8PROC_HANGUL_SBASE;
if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) {
@@ -728,28 +728,24 @@ UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom(
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE);
utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_DECOMPOSE));
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE);
utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_COMPOSE));
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT);
utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_DECOMPOSE|UTF8PROC_COMPAT));
return retval;
}
UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str) {
utf8proc_uint8_t *retval;
utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
utf8proc_map(str, 0, &retval, cast(utf8proc_option_t)(UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_COMPOSE|UTF8PROC_COMPAT));
return retval;
}