mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Remove auto
This commit is contained in:
+1
-17
@@ -473,22 +473,6 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
|
|||||||
|
|
||||||
void check_scope_usage(Checker *c, Scope *scope) {
|
void check_scope_usage(Checker *c, Scope *scope) {
|
||||||
// TODO(bill): Use this?
|
// TODO(bill): Use this?
|
||||||
#if 0
|
|
||||||
for_array(i, scope->elements.entries) {
|
|
||||||
auto *entry = scope->elements.entries + i;
|
|
||||||
Entity *e = entry->value;
|
|
||||||
if (e->kind == Entity_Variable) {
|
|
||||||
auto *v = &e->Variable;
|
|
||||||
if (!v->is_field && !v->used) {
|
|
||||||
warning(e->token, "Unused variable: %.*s", LIT(e->token.string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Scope *child = scope->first_child; child != NULL; child = child->next) {
|
|
||||||
check_scope_usage(c, child);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -961,7 +945,7 @@ void init_preload_types(Checker *c) {
|
|||||||
t_type_info = e->type;
|
t_type_info = e->type;
|
||||||
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
||||||
GB_ASSERT(is_type_union(e->type));
|
GB_ASSERT(is_type_union(e->type));
|
||||||
auto *record = &base_type(e->type)->Record;
|
TypeRecord *record = &base_type(e->type)->Record;
|
||||||
|
|
||||||
t_type_info_member = record->other_fields[0]->type;
|
t_type_info_member = record->other_fields[0]->type;
|
||||||
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
|||||||
if (o.type->kind != Type_Tuple) {
|
if (o.type->kind != Type_Tuple) {
|
||||||
array_add(&operands, o);
|
array_add(&operands, o);
|
||||||
} else {
|
} else {
|
||||||
auto *tuple = &o.type->Tuple;
|
TypeTuple *tuple = &o.type->Tuple;
|
||||||
for (isize j = 0; j < tuple->variable_count; j++) {
|
for (isize j = 0; j < tuple->variable_count; j++) {
|
||||||
o.type = tuple->variables[j]->type;
|
o.type = tuple->variables[j]->type;
|
||||||
array_add(&operands, o);
|
array_add(&operands, o);
|
||||||
@@ -315,8 +315,8 @@ void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, Cycle
|
|||||||
bool are_signatures_similar_enough(Type *a_, Type *b_) {
|
bool are_signatures_similar_enough(Type *a_, Type *b_) {
|
||||||
GB_ASSERT(a_->kind == Type_Proc);
|
GB_ASSERT(a_->kind == Type_Proc);
|
||||||
GB_ASSERT(b_->kind == Type_Proc);
|
GB_ASSERT(b_->kind == Type_Proc);
|
||||||
auto *a = &a_->Proc;
|
TypeProc *a = &a_->Proc;
|
||||||
auto *b = &b_->Proc;
|
TypeProc *b = &b_->Proc;
|
||||||
|
|
||||||
if (a->param_count != b->param_count) {
|
if (a->param_count != b->param_count) {
|
||||||
return false;
|
return false;
|
||||||
@@ -368,7 +368,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
if ((d->scope->is_file || d->scope->is_global) &&
|
if ((d->scope->is_file || d->scope->is_global) &&
|
||||||
str_eq(e->token.string, str_lit("main"))) {
|
str_eq(e->token.string, str_lit("main"))) {
|
||||||
if (proc_type != NULL) {
|
if (proc_type != NULL) {
|
||||||
auto *pt = &proc_type->Proc;
|
TypeProc *pt = &proc_type->Proc;
|
||||||
if (pt->param_count != 0 ||
|
if (pt->param_count != 0 ||
|
||||||
pt->result_count) {
|
pt->result_count) {
|
||||||
gbString str = type_to_string(proc_type);
|
gbString str = type_to_string(proc_type);
|
||||||
@@ -402,8 +402,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_foreign) {
|
if (is_foreign) {
|
||||||
auto *fp = &c->info.foreign_procs;
|
MapEntity *fp = &c->info.foreign_procs;
|
||||||
auto *proc_decl = &d->proc_decl->ProcDecl;
|
AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl;
|
||||||
String name = proc_decl->name->Ident.string;
|
String name = proc_decl->name->Ident.string;
|
||||||
if (proc_decl->foreign_name.len > 0) {
|
if (proc_decl->foreign_name.len > 0) {
|
||||||
name = proc_decl->foreign_name;
|
name = proc_decl->foreign_name;
|
||||||
@@ -425,8 +425,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
map_entity_set(fp, key, e);
|
map_entity_set(fp, key, e);
|
||||||
}
|
}
|
||||||
} else if (is_link_name) {
|
} else if (is_link_name) {
|
||||||
auto *fp = &c->info.foreign_procs;
|
MapEntity *fp = &c->info.foreign_procs;
|
||||||
auto *proc_decl = &d->proc_decl->ProcDecl;
|
AstNodeProcDecl *proc_decl = &d->proc_decl->ProcDecl;
|
||||||
String name = proc_decl->link_name;
|
String name = proc_decl->link_name;
|
||||||
|
|
||||||
HashKey key = hash_string(name);
|
HashKey key = hash_string(name);
|
||||||
@@ -492,7 +492,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
|
|||||||
|
|
||||||
GB_ASSERT(type->kind == Type_Proc);
|
GB_ASSERT(type->kind == Type_Proc);
|
||||||
if (type->Proc.param_count > 0) {
|
if (type->Proc.param_count > 0) {
|
||||||
auto *params = &type->Proc.params->Tuple;
|
TypeTuple *params = &type->Proc.params->Tuple;
|
||||||
for (isize i = 0; i < params->variable_count; i++) {
|
for (isize i = 0; i < params->variable_count; i++) {
|
||||||
Entity *e = params->variables[i];
|
Entity *e = params->variables[i];
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
|||||||
@@ -3401,7 +3401,7 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
|
|||||||
if (o.type->kind != Type_Tuple) {
|
if (o.type->kind != Type_Tuple) {
|
||||||
array_add(&operands, o);
|
array_add(&operands, o);
|
||||||
} else {
|
} else {
|
||||||
auto *tuple = &o.type->Tuple;
|
TypeTuple *tuple = &o.type->Tuple;
|
||||||
if (variadic && i >= param_count) {
|
if (variadic && i >= param_count) {
|
||||||
error(ast_node_token(ce->args.e[i]),
|
error(ast_node_token(ce->args.e[i]),
|
||||||
"`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
|
"`..` in a variadic procedure cannot be applied to a %td-valued expression", tuple->variable_count);
|
||||||
|
|||||||
@@ -441,7 +441,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
if (o.type->kind != Type_Tuple) {
|
if (o.type->kind != Type_Tuple) {
|
||||||
array_add(&operands, o);
|
array_add(&operands, o);
|
||||||
} else {
|
} else {
|
||||||
auto *tuple = &o.type->Tuple;
|
TypeTuple *tuple = &o.type->Tuple;
|
||||||
for (isize j = 0; j < tuple->variable_count; j++) {
|
for (isize j = 0; j < tuple->variable_count; j++) {
|
||||||
o.type = tuple->variables[j]->type;
|
o.type = tuple->variables[j]->type;
|
||||||
array_add(&operands, o);
|
array_add(&operands, o);
|
||||||
@@ -553,7 +553,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
if (result_count > 0) {
|
if (result_count > 0) {
|
||||||
Entity **variables = NULL;
|
Entity **variables = NULL;
|
||||||
if (proc_type->Proc.results != NULL) {
|
if (proc_type->Proc.results != NULL) {
|
||||||
auto *tuple = &proc_type->Proc.results->Tuple;
|
TypeTuple *tuple = &proc_type->Proc.results->Tuple;
|
||||||
variables = tuple->variables;
|
variables = tuple->variables;
|
||||||
}
|
}
|
||||||
if (rs->results.count == 0) {
|
if (rs->results.count == 0) {
|
||||||
|
|||||||
+82
-96
@@ -58,34 +58,6 @@ typedef struct BasicType {
|
|||||||
String name;
|
String name;
|
||||||
} BasicType;
|
} BasicType;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define TYPE_KINDS \
|
|
||||||
TYPE_KIND(Invalid), \
|
|
||||||
TYPE_KIND(Basic), \
|
|
||||||
TYPE_KIND(Pointer), \
|
|
||||||
TYPE_KIND(Array), \
|
|
||||||
TYPE_KIND(Vector), \
|
|
||||||
TYPE_KIND(Slice), \
|
|
||||||
TYPE_KIND(Maybe), \
|
|
||||||
TYPE_KIND(Record), \
|
|
||||||
TYPE_KIND(Named), \
|
|
||||||
TYPE_KIND(Tuple), \
|
|
||||||
TYPE_KIND(Proc), \
|
|
||||||
TYPE_KIND(Count),
|
|
||||||
|
|
||||||
typedef enum TypeKind {
|
|
||||||
#define TYPE_KIND(k, ...) GB_JOIN2(Type_, k)
|
|
||||||
TYPE_KINDS
|
|
||||||
#undef TYPE_KIND
|
|
||||||
} TypeKind;
|
|
||||||
|
|
||||||
String const type_strings[] = {
|
|
||||||
#define TYPE_KIND(k, ...) {cast(u8 *)#k, gb_size_of(#k)-1}
|
|
||||||
TYPE_KINDS
|
|
||||||
#undef TYPE_KIND
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum TypeRecordKind {
|
typedef enum TypeRecordKind {
|
||||||
TypeRecord_Invalid,
|
TypeRecord_Invalid,
|
||||||
|
|
||||||
@@ -97,75 +69,89 @@ typedef enum TypeRecordKind {
|
|||||||
TypeRecord_Count,
|
TypeRecord_Count,
|
||||||
} TypeRecordKind;
|
} TypeRecordKind;
|
||||||
|
|
||||||
|
typedef struct TypeRecord {
|
||||||
|
TypeRecordKind kind;
|
||||||
|
|
||||||
|
// All record types
|
||||||
|
// Theses are arrays
|
||||||
|
Entity **fields; // Entity_Variable (otherwise Entity_TypeName if union)
|
||||||
|
i32 field_count; // == offset_count is struct
|
||||||
|
AstNode *node;
|
||||||
|
|
||||||
|
union { // NOTE(bill): Reduce size_of Type
|
||||||
|
struct { // enum only
|
||||||
|
Type * enum_base; // Default is `int`
|
||||||
|
Entity * enum_count;
|
||||||
|
Entity * min_value;
|
||||||
|
Entity * max_value;
|
||||||
|
};
|
||||||
|
struct { // struct only
|
||||||
|
i64 * struct_offsets;
|
||||||
|
bool struct_are_offsets_set;
|
||||||
|
bool struct_is_packed;
|
||||||
|
bool struct_is_ordered;
|
||||||
|
Entity **fields_in_src_order; // Entity_Variable
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Entity_Constant or Entity_TypeName
|
||||||
|
Entity **other_fields;
|
||||||
|
i32 other_field_count;
|
||||||
|
} TypeRecord;
|
||||||
|
|
||||||
|
#define TYPE_KINDS \
|
||||||
|
TYPE_KIND(Basic, BasicType) \
|
||||||
|
TYPE_KIND(Pointer, struct { Type *elem; }) \
|
||||||
|
TYPE_KIND(Array, struct { Type *elem; i64 count; }) \
|
||||||
|
TYPE_KIND(Vector, struct { Type *elem; i64 count; }) \
|
||||||
|
TYPE_KIND(Slice, struct { Type *elem; }) \
|
||||||
|
TYPE_KIND(Maybe, struct { Type *elem; }) \
|
||||||
|
TYPE_KIND(Record, TypeRecord) \
|
||||||
|
TYPE_KIND(Named, struct { \
|
||||||
|
String name; \
|
||||||
|
Type * base; \
|
||||||
|
Entity *type_name; /* Entity_TypeName */ \
|
||||||
|
}) \
|
||||||
|
TYPE_KIND(Tuple, struct { \
|
||||||
|
Entity **variables; /* Entity_Variable */ \
|
||||||
|
i32 variable_count; \
|
||||||
|
bool are_offsets_set; \
|
||||||
|
i64 * offsets; \
|
||||||
|
}) \
|
||||||
|
TYPE_KIND(Proc, struct { \
|
||||||
|
Scope *scope; \
|
||||||
|
Type * params; /* Type_Tuple */ \
|
||||||
|
Type * results; /* Type_Tuple */ \
|
||||||
|
i32 param_count; \
|
||||||
|
i32 result_count; \
|
||||||
|
bool variadic; \
|
||||||
|
})
|
||||||
|
|
||||||
|
typedef 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")},
|
||||||
|
#define TYPE_KIND(k, ...) {cast(u8 *)#k, gb_size_of(#k)-1},
|
||||||
|
TYPE_KINDS
|
||||||
|
#undef TYPE_KIND
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TYPE_KIND(k, ...) typedef __VA_ARGS__ GB_JOIN2(Type, k);
|
||||||
|
TYPE_KINDS
|
||||||
|
#undef TYPE_KIND
|
||||||
|
|
||||||
typedef struct Type {
|
typedef struct Type {
|
||||||
TypeKind kind;
|
TypeKind kind;
|
||||||
union {
|
union {
|
||||||
BasicType Basic;
|
#define TYPE_KIND(k, ...) GB_JOIN2(Type, k) k;
|
||||||
struct {
|
TYPE_KINDS
|
||||||
Type *elem;
|
#undef TYPE_KIND
|
||||||
} Pointer;
|
|
||||||
struct {
|
|
||||||
Type *elem;
|
|
||||||
i64 count;
|
|
||||||
} Array;
|
|
||||||
struct {
|
|
||||||
Type *elem;
|
|
||||||
i64 count;
|
|
||||||
} Vector;
|
|
||||||
struct {
|
|
||||||
Type *elem;
|
|
||||||
} Slice;
|
|
||||||
struct {
|
|
||||||
Type *elem;
|
|
||||||
} Maybe;
|
|
||||||
struct {
|
|
||||||
TypeRecordKind kind;
|
|
||||||
|
|
||||||
// All record types
|
|
||||||
// Theses are arrays
|
|
||||||
Entity **fields; // Entity_Variable (otherwise Entity_TypeName if union)
|
|
||||||
i32 field_count; // == offset_count is struct
|
|
||||||
AstNode *node;
|
|
||||||
|
|
||||||
union { // NOTE(bill): Reduce size_of Type
|
|
||||||
struct { // enum only
|
|
||||||
Type * enum_base; // Default is `int`
|
|
||||||
Entity * enum_count;
|
|
||||||
Entity * min_value;
|
|
||||||
Entity * max_value;
|
|
||||||
};
|
|
||||||
struct { // struct only
|
|
||||||
i64 * struct_offsets;
|
|
||||||
bool struct_are_offsets_set;
|
|
||||||
bool struct_is_packed;
|
|
||||||
bool struct_is_ordered;
|
|
||||||
Entity **fields_in_src_order; // Entity_Variable
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Entity_Constant or Entity_TypeName
|
|
||||||
Entity **other_fields;
|
|
||||||
i32 other_field_count;
|
|
||||||
} Record;
|
|
||||||
struct {
|
|
||||||
String name;
|
|
||||||
Type * base;
|
|
||||||
Entity *type_name; // Entity_TypeName
|
|
||||||
} Named;
|
|
||||||
struct {
|
|
||||||
Entity **variables; // Entity_Variable
|
|
||||||
i32 variable_count;
|
|
||||||
bool are_offsets_set;
|
|
||||||
i64 * offsets;
|
|
||||||
} Tuple;
|
|
||||||
struct {
|
|
||||||
Scope *scope;
|
|
||||||
Type * params; // Type_Tuple
|
|
||||||
Type * results; // Type_Tuple
|
|
||||||
i32 param_count;
|
|
||||||
i32 result_count;
|
|
||||||
bool variadic;
|
|
||||||
} Proc;
|
|
||||||
};
|
};
|
||||||
} Type;
|
} Type;
|
||||||
|
|
||||||
@@ -186,9 +172,9 @@ typedef Array(isize) Array_isize;
|
|||||||
typedef struct Selection {
|
typedef struct Selection {
|
||||||
Entity * entity;
|
Entity * entity;
|
||||||
Array_isize index;
|
Array_isize index;
|
||||||
bool indirect; // Set if there was a pointer deref anywhere down the line
|
bool indirect; // Set if there was a pointer deref anywhere down the line
|
||||||
} Selection;
|
} Selection;
|
||||||
Selection empty_selection = {};
|
Selection empty_selection = {0};
|
||||||
|
|
||||||
Selection make_selection(Entity *entity, Array_isize index, bool indirect) {
|
Selection make_selection(Entity *entity, Array_isize index, bool indirect) {
|
||||||
Selection s = {entity, index, indirect};
|
Selection s = {entity, index, indirect};
|
||||||
|
|||||||
-303
@@ -246,306 +246,3 @@ i16 f32_to_f16(f32 value) {
|
|||||||
#define MAP_FUNC map_isize_
|
#define MAP_FUNC map_isize_
|
||||||
#define MAP_NAME MapIsize
|
#define MAP_NAME MapIsize
|
||||||
#include "map.c"
|
#include "map.c"
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#ifndef MAP_FIND_RESULT
|
|
||||||
#define MAP_FIND_RESULT
|
|
||||||
typedef struct MapFindResult {
|
|
||||||
isize hash_index;
|
|
||||||
isize entry_prev;
|
|
||||||
isize entry_index;
|
|
||||||
} MapFindResult;
|
|
||||||
#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 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);
|
|
||||||
|
|
||||||
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 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_reserve(&h->hashes, a, capacity);
|
|
||||||
array_init_reserve(&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 = 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
gb_internal MapFindResult map__find(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.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
gb_internal bool 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 = GB_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 = {0};
|
|
||||||
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.e[i] = -1;
|
|
||||||
}
|
|
||||||
for (i = 0; i < h->entries.count; i++) {
|
|
||||||
MapEntry<T> *e = &h->entries.e[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.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 (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.e[index].value;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void map_set(Map<T> *h, HashKey key, T 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.e[fr.entry_prev].next = index;
|
|
||||||
} else {
|
|
||||||
h->hashes.e[fr.hash_index] = index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h->entries.e[index].value = value;
|
|
||||||
|
|
||||||
if (map__full(h))
|
|
||||||
map_grow(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void map__erase(Map<T> *h, MapFindResult fr) {
|
|
||||||
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];
|
|
||||||
MapFindResult last = map__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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
gb_array_clear(h->hashes);
|
|
||||||
gb_array_clear(h->entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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.e[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.e[i].key, e->key)) {
|
|
||||||
return &h->entries.e[i];
|
|
||||||
}
|
|
||||||
i = h->entries.e[i].next;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
isize multi_map_count(Map<T> *h, HashKey key) {
|
|
||||||
isize count = 0;
|
|
||||||
auto *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;
|
|
||||||
auto *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 value) {
|
|
||||||
if (h->hashes.count == 0) {
|
|
||||||
map_grow(h);
|
|
||||||
}
|
|
||||||
MapFindResult fr = map__find(h, key);
|
|
||||||
isize i = map__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;
|
|
||||||
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(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
|
|
||||||
|
|||||||
@@ -0,0 +1,301 @@
|
|||||||
|
/*
|
||||||
|
Example of usage:
|
||||||
|
|
||||||
|
#define MAP_TYPE String
|
||||||
|
#define MAP_FUNC map_string_
|
||||||
|
#define MAP_NAME MapString
|
||||||
|
#include "map.c"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MAP_FIND_RESULT
|
||||||
|
#define MAP_FIND_RESULT
|
||||||
|
// NOTE(bill): This is the same for every `Map`
|
||||||
|
typedef struct MapFindResult {
|
||||||
|
isize hash_index;
|
||||||
|
isize entry_prev;
|
||||||
|
isize entry_index;
|
||||||
|
} MapFindResult;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _J2(a,b) GB_JOIN2(a,b)
|
||||||
|
|
||||||
|
/*
|
||||||
|
MAP_TYPE - Entry type
|
||||||
|
MAP_FUNC - 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_FUNC,init) (MAP_NAME *h, gbAllocator a);
|
||||||
|
void _J2(MAP_FUNC,init_with_reserve)(MAP_NAME *h, gbAllocator a, isize capacity);
|
||||||
|
void _J2(MAP_FUNC,destroy) (MAP_NAME *h);
|
||||||
|
MAP_TYPE *_J2(MAP_FUNC,get) (MAP_NAME *h, HashKey key);
|
||||||
|
void _J2(MAP_FUNC,set) (MAP_NAME *h, HashKey key, MAP_TYPE value);
|
||||||
|
void _J2(MAP_FUNC,remove) (MAP_NAME *h, HashKey key);
|
||||||
|
void _J2(MAP_FUNC,clear) (MAP_NAME *h);
|
||||||
|
void _J2(MAP_FUNC,grow) (MAP_NAME *h);
|
||||||
|
void _J2(MAP_FUNC,rehash) (MAP_NAME *h, isize new_count);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
MAP_ENTRY *_J2(MAP_FUNC,multi_find_first)(MAP_NAME *h, HashKey key);
|
||||||
|
MAP_ENTRY *_J2(MAP_FUNC,multi_find_next) (MAP_NAME *h, MAP_ENTRY *e);
|
||||||
|
|
||||||
|
isize _J2(MAP_FUNC,multi_count) (MAP_NAME *h, HashKey key);
|
||||||
|
void _J2(MAP_FUNC,multi_get_all) (MAP_NAME *h, HashKey key, MAP_TYPE *items);
|
||||||
|
void _J2(MAP_FUNC,multi_insert) (MAP_NAME *h, HashKey key, MAP_TYPE value);
|
||||||
|
void _J2(MAP_FUNC,multi_remove) (MAP_NAME *h, HashKey key, MAP_ENTRY *e);
|
||||||
|
void _J2(MAP_FUNC,multi_remove_all)(MAP_NAME *h, HashKey key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
gb_inline void _J2(MAP_FUNC,init)(MAP_NAME *h, gbAllocator a) {
|
||||||
|
array_init(&h->hashes, a);
|
||||||
|
array_init(&h->entries, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline void _J2(MAP_FUNC,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_FUNC,destroy)(MAP_NAME *h) {
|
||||||
|
array_free(&h->entries);
|
||||||
|
array_free(&h->hashes);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal isize _J2(MAP_FUNC,_add_entry)(MAP_NAME *h, HashKey key) {
|
||||||
|
MAP_ENTRY e = {};
|
||||||
|
e.key = key;
|
||||||
|
e.next = -1;
|
||||||
|
array_add(&h->entries, e);
|
||||||
|
return h->entries.count-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal MapFindResult _J2(MAP_FUNC,_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_FUNC,_find)(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_FUNC,_full)(MAP_NAME *h) {
|
||||||
|
return 0.75f * h->hashes.count <= h->entries.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline void _J2(MAP_FUNC,grow)(MAP_NAME *h) {
|
||||||
|
isize new_count = ARRAY_GROW_FORMULA(h->entries.count);
|
||||||
|
_J2(MAP_FUNC,rehash)(h, new_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _J2(MAP_FUNC,rehash)(MAP_NAME *h, isize new_count) {
|
||||||
|
isize i, j;
|
||||||
|
MAP_NAME nh = {0};
|
||||||
|
_J2(MAP_FUNC,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_FUNC,grow)(&nh);
|
||||||
|
}
|
||||||
|
fr = _J2(MAP_FUNC,_find)(&nh, e->key);
|
||||||
|
j = _J2(MAP_FUNC,_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_FUNC,_full)(&nh)) {
|
||||||
|
_J2(MAP_FUNC,grow)(&nh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_J2(MAP_FUNC,destroy)(h);
|
||||||
|
*h = nh;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline MAP_TYPE *_J2(MAP_FUNC,get)(MAP_NAME *h, HashKey key) {
|
||||||
|
isize index = _J2(MAP_FUNC,_find)(h, key).entry_index;
|
||||||
|
if (index >= 0) {
|
||||||
|
return &h->entries.e[index].value;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _J2(MAP_FUNC,set)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
|
||||||
|
isize index;
|
||||||
|
MapFindResult fr;
|
||||||
|
if (h->hashes.count == 0)
|
||||||
|
_J2(MAP_FUNC,grow)(h);
|
||||||
|
fr = _J2(MAP_FUNC,_find)(h, key);
|
||||||
|
if (fr.entry_index >= 0) {
|
||||||
|
index = fr.entry_index;
|
||||||
|
} else {
|
||||||
|
index = _J2(MAP_FUNC,_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_FUNC,_full)(h)) {
|
||||||
|
_J2(MAP_FUNC,grow)(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void _J2(MAP_FUNC,_erase)(MAP_NAME *h, MapFindResult fr) {
|
||||||
|
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];
|
||||||
|
MapFindResult last = _J2(MAP_FUNC,_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_FUNC,remove)(MAP_NAME *h, HashKey key) {
|
||||||
|
MapFindResult fr = _J2(MAP_FUNC,_find)(h, key);
|
||||||
|
if (fr.entry_index >= 0) {
|
||||||
|
_J2(MAP_FUNC,_erase)(h, fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline void _J2(MAP_FUNC,clear)(MAP_NAME *h) {
|
||||||
|
array_clear(&h->hashes);
|
||||||
|
array_clear(&h->entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
MAP_ENTRY *_J2(MAP_FUNC,multi_find_first)(MAP_NAME *h, HashKey key) {
|
||||||
|
isize i = _J2(MAP_FUNC,_find)(h, key).entry_index;
|
||||||
|
if (i < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return &h->entries.e[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
MAP_ENTRY *_J2(MAP_FUNC,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_FUNC,multi_count)(MAP_NAME *h, HashKey key) {
|
||||||
|
isize count = 0;
|
||||||
|
auto *e = _J2(MAP_FUNC,multi_find_first)(h, key);
|
||||||
|
while (e != NULL) {
|
||||||
|
count++;
|
||||||
|
e = _J2(MAP_FUNC,multi_find_next)(h, e);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _J2(MAP_FUNC,multi_get_all)(MAP_NAME *h, HashKey key, MAP_TYPE *items) {
|
||||||
|
isize i = 0;
|
||||||
|
auto *e = _J2(MAP_FUNC,multi_find_first)(h, key);
|
||||||
|
while (e != NULL) {
|
||||||
|
items[i++] = e->value;
|
||||||
|
e = _J2(MAP_FUNC,multi_find_next)(h, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _J2(MAP_FUNC,multi_insert)(MAP_NAME *h, HashKey key, MAP_TYPE value) {
|
||||||
|
if (h->hashes.count == 0) {
|
||||||
|
_J2(MAP_FUNC,grow)(h);
|
||||||
|
}
|
||||||
|
MapFindResult fr = _J2(MAP_FUNC,_find)(h, key);
|
||||||
|
isize i = _J2(MAP_FUNC,_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;
|
||||||
|
if (_J2(MAP_FUNC,_full)(h)) {
|
||||||
|
_J2(MAP_FUNC,grow)(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _J2(MAP_FUNC,multi_remove)(MAP_NAME *h, HashKey key, MAP_ENTRY *e) {
|
||||||
|
MapFindResult fr = _J2(MAP_FUNC,_find)(h, e);
|
||||||
|
if (fr.entry_index >= 0) {
|
||||||
|
_J2(MAP_FUNC,_erase)(h, fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _J2(MAP_FUNC,multi_remove_all)(MAP_NAME *h, HashKey key) {
|
||||||
|
while (_J2(MAP_FUNC,get)(h, key) != NULL) {
|
||||||
|
_J2(MAP_FUNC,remove)(h, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#undef _J2
|
||||||
|
#undef MAP_TYPE
|
||||||
|
#undef MAP_FUNC
|
||||||
|
#undef MAP_NAME
|
||||||
|
#undef MAP_ENTRY
|
||||||
+5
-5
@@ -430,7 +430,7 @@ vmValue vm_operand_value(VirtualMachine *vm, ssaValue *value) {
|
|||||||
v = vm_exact_value(vm, value, value->Constant.value, value->Constant.type);
|
v = vm_exact_value(vm, value, value->Constant.value, value->Constant.type);
|
||||||
} break;
|
} break;
|
||||||
case ssaValue_ConstantSlice: {
|
case ssaValue_ConstantSlice: {
|
||||||
auto *cs = &value->ConstantSlice;
|
ssaValueConstant *cs = &value->ConstantSlice;
|
||||||
v = vm_make_value_comp(ssa_type(value), vm->stack_allocator, 3);
|
v = vm_make_value_comp(ssa_type(value), vm->stack_allocator, 3);
|
||||||
v.val_comp[0] = vm_operand_value(vm, cs->backing_array);
|
v.val_comp[0] = vm_operand_value(vm, cs->backing_array);
|
||||||
v.val_comp[1] = vm_make_value_int(t_int, cs->count);
|
v.val_comp[1] = vm_make_value_int(t_int, cs->count);
|
||||||
@@ -1120,7 +1120,7 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_BinaryOp: {
|
case ssaInstr_BinaryOp: {
|
||||||
auto *bo = &instr->BinaryOp;
|
ssaInstrBinaryOp *bo = &instr->BinaryOp;
|
||||||
Type *type = ssa_type(bo->left);
|
Type *type = ssa_type(bo->left);
|
||||||
vmValue lhs = vm_operand_value(vm, bo->left);
|
vmValue lhs = vm_operand_value(vm, bo->left);
|
||||||
vmValue rhs = vm_operand_value(vm, bo->right);
|
vmValue rhs = vm_operand_value(vm, bo->right);
|
||||||
@@ -1171,7 +1171,7 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_VectorShuffle: {
|
case ssaInstr_VectorShuffle: {
|
||||||
auto *vs = &instr->VectorShuffle;
|
ssaValueVectorShuffle *vs = &instr->VectorShuffle;
|
||||||
vmValue old_vector = vm_operand_value(vm, instr->VectorShuffle.vector);
|
vmValue old_vector = vm_operand_value(vm, instr->VectorShuffle.vector);
|
||||||
vmValue new_vector = vm_make_value_comp(ssa_type(value), vm->stack_allocator, vs->index_count);
|
vmValue new_vector = vm_make_value_comp(ssa_type(value), vm->stack_allocator, vs->index_count);
|
||||||
|
|
||||||
@@ -1183,7 +1183,7 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_BoundsCheck: {
|
case ssaInstr_BoundsCheck: {
|
||||||
auto *bc = &instr->BoundsCheck;
|
ssaInstrBoundsCheck *bc = &instr->BoundsCheck;
|
||||||
Array<vmValue> args = {};
|
Array<vmValue> args = {};
|
||||||
array_init(&args, vm->stack_allocator, 5);
|
array_init(&args, vm->stack_allocator, 5);
|
||||||
array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string));
|
array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string));
|
||||||
@@ -1196,7 +1196,7 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_SliceBoundsCheck: {
|
case ssaInstr_SliceBoundsCheck: {
|
||||||
auto *bc = &instr->SliceBoundsCheck;
|
ssaInstrSliceBoundsCheck *bc = &instr->SliceBoundsCheck;
|
||||||
Array<vmValue> args = {};
|
Array<vmValue> args = {};
|
||||||
|
|
||||||
array_init(&args, vm->stack_allocator, 7);
|
array_init(&args, vm->stack_allocator, 7);
|
||||||
|
|||||||
+6
-5
@@ -101,7 +101,6 @@ AstNodeArray make_ast_node_array(AstFile *f) {
|
|||||||
|
|
||||||
|
|
||||||
#define AST_NODE_KINDS \
|
#define AST_NODE_KINDS \
|
||||||
AST_NODE_KIND(Invalid, "invalid node", struct{}) \
|
|
||||||
AST_NODE_KIND(BasicLit, "basic literal", Token) \
|
AST_NODE_KIND(BasicLit, "basic literal", Token) \
|
||||||
AST_NODE_KIND(Ident, "identifier", Token) \
|
AST_NODE_KIND(Ident, "identifier", Token) \
|
||||||
AST_NODE_KIND(Ellipsis, "ellipsis", struct { \
|
AST_NODE_KIND(Ellipsis, "ellipsis", struct { \
|
||||||
@@ -317,16 +316,18 @@ AST_NODE_KIND(_TypeBegin, "", struct{}) \
|
|||||||
AstNode *base_type; \
|
AstNode *base_type; \
|
||||||
AstNodeArray fields; \
|
AstNodeArray fields; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_TypeEnd, "", struct{}) \
|
AST_NODE_KIND(_TypeEnd, "", struct{})
|
||||||
AST_NODE_KIND(Count, "", struct{})
|
|
||||||
|
|
||||||
typedef enum AstNodeKind {
|
typedef enum AstNodeKind {
|
||||||
|
AstNode_Invalid,
|
||||||
#define AST_NODE_KIND(_kind_name_, ...) GB_JOIN2(AstNode_, _kind_name_),
|
#define AST_NODE_KIND(_kind_name_, ...) GB_JOIN2(AstNode_, _kind_name_),
|
||||||
AST_NODE_KINDS
|
AST_NODE_KINDS
|
||||||
#undef AST_NODE_KIND
|
#undef AST_NODE_KIND
|
||||||
|
AstNode_Count,
|
||||||
} AstNodeKind;
|
} AstNodeKind;
|
||||||
|
|
||||||
String const ast_node_strings[] = {
|
String const ast_node_strings[] = {
|
||||||
|
{cast(u8 *)"invalid node", gb_size_of("invalid node")},
|
||||||
#define AST_NODE_KIND(_kind_name_, name, ...) {cast(u8 *)name, gb_size_of(name)-1},
|
#define AST_NODE_KIND(_kind_name_, name, ...) {cast(u8 *)name, gb_size_of(name)-1},
|
||||||
AST_NODE_KINDS
|
AST_NODE_KINDS
|
||||||
#undef AST_NODE_KIND
|
#undef AST_NODE_KIND
|
||||||
@@ -3101,7 +3102,7 @@ void parse_file(Parser *p, AstFile *f) {
|
|||||||
syntax_error(ast_node_token(node), "Only declarations are allowed at file scope");
|
syntax_error(ast_node_token(node), "Only declarations are allowed at file scope");
|
||||||
} else {
|
} else {
|
||||||
if (node->kind == AstNode_ImportDecl) {
|
if (node->kind == AstNode_ImportDecl) {
|
||||||
auto *id = &node->ImportDecl;
|
AstNodeImportDecl *id = &node->ImportDecl;
|
||||||
String file_str = id->relpath.string;
|
String file_str = id->relpath.string;
|
||||||
|
|
||||||
if (!is_import_path_valid(file_str)) {
|
if (!is_import_path_valid(file_str)) {
|
||||||
@@ -3130,7 +3131,7 @@ void parse_file(Parser *p, AstFile *f) {
|
|||||||
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
|
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
|
||||||
|
|
||||||
} else if (node->kind == AstNode_ForeignLibrary) {
|
} else if (node->kind == AstNode_ForeignLibrary) {
|
||||||
auto *id = &node->ForeignLibrary;
|
AstNodeForeignLibrary *id = &node->ForeignLibrary;
|
||||||
String file_str = id->filepath.string;
|
String file_str = id->filepath.string;
|
||||||
|
|
||||||
if (!is_import_path_valid(file_str)) {
|
if (!is_import_path_valid(file_str)) {
|
||||||
|
|||||||
+182
-211
@@ -131,73 +131,152 @@ struct ssaProcedure {
|
|||||||
|
|
||||||
|
|
||||||
#define SSA_INSTR_KINDS \
|
#define SSA_INSTR_KINDS \
|
||||||
SSA_INSTR_KIND(Invalid), \
|
SSA_INSTR_KIND(Comment, struct { String text; }) \
|
||||||
SSA_INSTR_KIND(Comment), \
|
SSA_INSTR_KIND(Local, struct { \
|
||||||
SSA_INSTR_KIND(Local), \
|
Entity * entity; \
|
||||||
SSA_INSTR_KIND(ZeroInit), \
|
Type * type; \
|
||||||
SSA_INSTR_KIND(Store), \
|
bool zero_initialized; \
|
||||||
SSA_INSTR_KIND(Load), \
|
ssaValueArray referrers; \
|
||||||
SSA_INSTR_KIND(PtrOffset), \
|
}) \
|
||||||
SSA_INSTR_KIND(ArrayElementPtr), \
|
SSA_INSTR_KIND(ZeroInit, struct { ssaValue *address; }) \
|
||||||
SSA_INSTR_KIND(StructElementPtr), \
|
SSA_INSTR_KIND(Store, struct { ssaValue *address, *value; }) \
|
||||||
SSA_INSTR_KIND(ArrayExtractValue), \
|
SSA_INSTR_KIND(Load, struct { Type *type; ssaValue *address; }) \
|
||||||
SSA_INSTR_KIND(StructExtractValue), \
|
SSA_INSTR_KIND(PtrOffset, struct { \
|
||||||
SSA_INSTR_KIND(UnionTagPtr), \
|
ssaValue *address; \
|
||||||
SSA_INSTR_KIND(UnionTagValue), \
|
ssaValue *offset; \
|
||||||
SSA_INSTR_KIND(Conv), \
|
}) \
|
||||||
SSA_INSTR_KIND(Jump), \
|
SSA_INSTR_KIND(ArrayElementPtr, struct { \
|
||||||
SSA_INSTR_KIND(If), \
|
ssaValue *address; \
|
||||||
SSA_INSTR_KIND(Return), \
|
Type * result_type; \
|
||||||
SSA_INSTR_KIND(Select), \
|
ssaValue *elem_index; \
|
||||||
SSA_INSTR_KIND(Phi), \
|
}) \
|
||||||
SSA_INSTR_KIND(Unreachable), \
|
SSA_INSTR_KIND(StructElementPtr, struct { \
|
||||||
SSA_INSTR_KIND(BinaryOp), \
|
ssaValue *address; \
|
||||||
SSA_INSTR_KIND(Call), \
|
Type * result_type; \
|
||||||
SSA_INSTR_KIND(VectorExtractElement), \
|
i32 elem_index; \
|
||||||
SSA_INSTR_KIND(VectorInsertElement), \
|
}) \
|
||||||
SSA_INSTR_KIND(VectorShuffle), \
|
SSA_INSTR_KIND(ArrayExtractValue, struct { \
|
||||||
SSA_INSTR_KIND(StartupRuntime), \
|
ssaValue *address; \
|
||||||
SSA_INSTR_KIND(BoundsCheck), \
|
Type * result_type; \
|
||||||
SSA_INSTR_KIND(SliceBoundsCheck), \
|
i32 index; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(StructExtractValue, struct { \
|
||||||
|
ssaValue *address; \
|
||||||
|
Type * result_type; \
|
||||||
|
i32 index; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(UnionTagPtr, struct { \
|
||||||
|
ssaValue *address; \
|
||||||
|
Type *type; /* ^int */ \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(UnionTagValue, struct { \
|
||||||
|
ssaValue *address; \
|
||||||
|
Type *type; /* int */ \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(Conv, struct { \
|
||||||
|
ssaConvKind kind; \
|
||||||
|
ssaValue *value; \
|
||||||
|
Type *from, *to; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(Jump, struct { ssaBlock *block; }) \
|
||||||
|
SSA_INSTR_KIND(If, struct { \
|
||||||
|
ssaValue *cond; \
|
||||||
|
ssaBlock *true_block; \
|
||||||
|
ssaBlock *false_block; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(Return, struct { ssaValue *value; }) \
|
||||||
|
SSA_INSTR_KIND(Select, struct { \
|
||||||
|
ssaValue *cond; \
|
||||||
|
ssaValue *true_value; \
|
||||||
|
ssaValue *false_value; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(Phi, struct { ssaValueArray edges; Type *type; }) \
|
||||||
|
SSA_INSTR_KIND(Unreachable, struct {}) \
|
||||||
|
SSA_INSTR_KIND(BinaryOp, struct { \
|
||||||
|
Type * type; \
|
||||||
|
TokenKind op; \
|
||||||
|
ssaValue *left, *right; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(Call, struct { \
|
||||||
|
Type * type; /* return type */ \
|
||||||
|
ssaValue *value; \
|
||||||
|
ssaValue **args; \
|
||||||
|
isize arg_count; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(VectorExtractElement, struct { \
|
||||||
|
ssaValue *vector; \
|
||||||
|
ssaValue *index; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(VectorInsertElement, struct { \
|
||||||
|
ssaValue *vector; \
|
||||||
|
ssaValue *elem; \
|
||||||
|
ssaValue *index; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(VectorShuffle, struct { \
|
||||||
|
ssaValue *vector; \
|
||||||
|
i32 * indices; \
|
||||||
|
i32 index_count; \
|
||||||
|
Type * type; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(StartupRuntime, struct {}) \
|
||||||
|
SSA_INSTR_KIND(BoundsCheck, struct { \
|
||||||
|
TokenPos pos; \
|
||||||
|
ssaValue *index; \
|
||||||
|
ssaValue *len; \
|
||||||
|
}) \
|
||||||
|
SSA_INSTR_KIND(SliceBoundsCheck, struct { \
|
||||||
|
TokenPos pos; \
|
||||||
|
ssaValue *low; \
|
||||||
|
ssaValue *high; \
|
||||||
|
ssaValue *max; \
|
||||||
|
bool is_substring; \
|
||||||
|
})
|
||||||
|
|
||||||
#define SSA_CONV_KINDS \
|
#define SSA_CONV_KINDS \
|
||||||
SSA_CONV_KIND(Invalid), \
|
SSA_CONV_KIND(trunc) \
|
||||||
SSA_CONV_KIND(trunc), \
|
SSA_CONV_KIND(zext) \
|
||||||
SSA_CONV_KIND(zext), \
|
SSA_CONV_KIND(fptrunc) \
|
||||||
SSA_CONV_KIND(fptrunc), \
|
SSA_CONV_KIND(fpext) \
|
||||||
SSA_CONV_KIND(fpext), \
|
SSA_CONV_KIND(fptoui) \
|
||||||
SSA_CONV_KIND(fptoui), \
|
SSA_CONV_KIND(fptosi) \
|
||||||
SSA_CONV_KIND(fptosi), \
|
SSA_CONV_KIND(uitofp) \
|
||||||
SSA_CONV_KIND(uitofp), \
|
SSA_CONV_KIND(sitofp) \
|
||||||
SSA_CONV_KIND(sitofp), \
|
SSA_CONV_KIND(ptrtoint) \
|
||||||
SSA_CONV_KIND(ptrtoint), \
|
SSA_CONV_KIND(inttoptr) \
|
||||||
SSA_CONV_KIND(inttoptr), \
|
SSA_CONV_KIND(bitcast)
|
||||||
SSA_CONV_KIND(bitcast),
|
|
||||||
|
|
||||||
typedef enum ssaInstrKind {
|
typedef enum ssaInstrKind {
|
||||||
#define SSA_INSTR_KIND(x) GB_JOIN2(ssaInstr_, x)
|
ssaInstr_Invalid,
|
||||||
|
#define SSA_INSTR_KIND(x, ...) GB_JOIN2(ssaInstr_, x),
|
||||||
SSA_INSTR_KINDS
|
SSA_INSTR_KINDS
|
||||||
#undef SSA_INSTR_KIND
|
#undef SSA_INSTR_KIND
|
||||||
} ssaInstrKind;
|
} ssaInstrKind;
|
||||||
|
|
||||||
String const ssa_instr_strings[] = {
|
String const ssa_instr_strings[] = {
|
||||||
#define SSA_INSTR_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1}
|
{cast(u8 *)"Invalid", gb_size_of("Invalid")-1},
|
||||||
|
#define SSA_INSTR_KIND(x, ...) {cast(u8 *)#x, gb_size_of(#x)-1},
|
||||||
SSA_INSTR_KINDS
|
SSA_INSTR_KINDS
|
||||||
#undef SSA_INSTR_KIND
|
#undef SSA_INSTR_KIND
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum ssaConvKind {
|
typedef enum ssaConvKind {
|
||||||
#define SSA_CONV_KIND(x) GB_JOIN2(ssaConv_, x)
|
ssaConv_Invalid,
|
||||||
|
#define SSA_CONV_KIND(x) GB_JOIN2(ssaConv_, x),
|
||||||
SSA_CONV_KINDS
|
SSA_CONV_KINDS
|
||||||
#undef SSA_CONV_KIND
|
#undef SSA_CONV_KIND
|
||||||
} ssaConvKind;
|
} ssaConvKind;
|
||||||
|
|
||||||
String const ssa_conv_strings[] = {
|
String const ssa_conv_strings[] = {
|
||||||
#define SSA_CONV_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1}
|
{cast(u8 *)"Invalid", gb_size_of("Invalid")-1},
|
||||||
|
#define SSA_CONV_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1},
|
||||||
SSA_CONV_KINDS
|
SSA_CONV_KINDS
|
||||||
#undef SSA_CONV_KIND
|
#undef SSA_CONV_KIND
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SSA_INSTR_KIND(k, ...) typedef __VA_ARGS__ GB_JOIN2(ssaInstr, k);
|
||||||
|
SSA_INSTR_KINDS
|
||||||
|
#undef SSA_INSTR_KIND
|
||||||
|
|
||||||
typedef struct ssaInstr ssaInstr;
|
typedef struct ssaInstr ssaInstr;
|
||||||
struct ssaInstr {
|
struct ssaInstr {
|
||||||
ssaInstrKind kind;
|
ssaInstrKind kind;
|
||||||
@@ -206,129 +285,9 @@ struct ssaInstr {
|
|||||||
Type *type;
|
Type *type;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
#define SSA_INSTR_KIND(k, ...) GB_JOIN2(ssaInstr, k) k;
|
||||||
String text;
|
SSA_INSTR_KINDS
|
||||||
} Comment;
|
#undef SSA_INSTR_KIND
|
||||||
struct {
|
|
||||||
Entity * entity;
|
|
||||||
Type * type;
|
|
||||||
bool zero_initialized;
|
|
||||||
ssaValueArray referrers;
|
|
||||||
} Local;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
} ZeroInit;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
ssaValue *value;
|
|
||||||
} Store;
|
|
||||||
struct {
|
|
||||||
Type *type;
|
|
||||||
ssaValue *address;
|
|
||||||
} Load;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
Type * result_type;
|
|
||||||
ssaValue *elem_index;
|
|
||||||
} ArrayElementPtr;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
Type * result_type;
|
|
||||||
i32 elem_index;
|
|
||||||
} StructElementPtr;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
ssaValue *offset;
|
|
||||||
} PtrOffset;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
Type * result_type;
|
|
||||||
i32 index;
|
|
||||||
} ArrayExtractValue;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
Type * result_type;
|
|
||||||
i32 index;
|
|
||||||
} StructExtractValue;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
Type *type; // ^int
|
|
||||||
} UnionTagPtr;
|
|
||||||
struct {
|
|
||||||
ssaValue *address;
|
|
||||||
Type *type; // int
|
|
||||||
} UnionTagValue;
|
|
||||||
struct {
|
|
||||||
ssaValue *value;
|
|
||||||
ssaValue *elem;
|
|
||||||
i32 index;
|
|
||||||
} InsertValue;
|
|
||||||
struct {
|
|
||||||
ssaConvKind kind;
|
|
||||||
ssaValue *value;
|
|
||||||
Type *from, *to;
|
|
||||||
} Conv;
|
|
||||||
struct {
|
|
||||||
ssaBlock *block;
|
|
||||||
} Jump;
|
|
||||||
struct {
|
|
||||||
ssaValue *cond;
|
|
||||||
ssaBlock *true_block;
|
|
||||||
ssaBlock *false_block;
|
|
||||||
} If;
|
|
||||||
struct {
|
|
||||||
ssaValue *value;
|
|
||||||
} Return;
|
|
||||||
struct {} Unreachable;
|
|
||||||
struct {
|
|
||||||
ssaValue *cond;
|
|
||||||
ssaValue *true_value;
|
|
||||||
ssaValue *false_value;
|
|
||||||
} Select;
|
|
||||||
struct {
|
|
||||||
ssaValueArray edges;
|
|
||||||
Type *type;
|
|
||||||
} Phi;
|
|
||||||
struct {
|
|
||||||
Type *type;
|
|
||||||
TokenKind op;
|
|
||||||
ssaValue *left, *right;
|
|
||||||
} BinaryOp;
|
|
||||||
struct {
|
|
||||||
Type *type; // return type
|
|
||||||
ssaValue *value;
|
|
||||||
ssaValue **args;
|
|
||||||
isize arg_count;
|
|
||||||
} Call;
|
|
||||||
struct {
|
|
||||||
ssaValue *vector;
|
|
||||||
ssaValue *index;
|
|
||||||
} VectorExtractElement;
|
|
||||||
struct {
|
|
||||||
ssaValue *vector;
|
|
||||||
ssaValue *elem;
|
|
||||||
ssaValue *index;
|
|
||||||
} VectorInsertElement;
|
|
||||||
struct {
|
|
||||||
ssaValue *vector;
|
|
||||||
i32 *indices;
|
|
||||||
i32 index_count;
|
|
||||||
Type *type;
|
|
||||||
} VectorShuffle;
|
|
||||||
|
|
||||||
struct {} StartupRuntime;
|
|
||||||
struct {
|
|
||||||
TokenPos pos;
|
|
||||||
ssaValue *index;
|
|
||||||
ssaValue *len;
|
|
||||||
} BoundsCheck;
|
|
||||||
struct {
|
|
||||||
TokenPos pos;
|
|
||||||
ssaValue *low;
|
|
||||||
ssaValue *high;
|
|
||||||
ssaValue *max;
|
|
||||||
bool is_substring;
|
|
||||||
} SliceBoundsCheck;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -350,45 +309,57 @@ typedef enum ssaValueKind {
|
|||||||
ssaValue_Count,
|
ssaValue_Count,
|
||||||
} ssaValueKind;
|
} ssaValueKind;
|
||||||
|
|
||||||
|
typedef struct ssaValueConstant {
|
||||||
|
Type * type;
|
||||||
|
ExactValue value;
|
||||||
|
} ssaValueConstant;
|
||||||
|
|
||||||
|
typedef struct ssaValueConstantSlice {
|
||||||
|
Type * type;
|
||||||
|
ssaValue *backing_array;
|
||||||
|
i64 count;
|
||||||
|
} ssaValueConstantSlice;
|
||||||
|
|
||||||
|
typedef struct ssaValueNil {
|
||||||
|
Type *type;
|
||||||
|
} ssaValueNil;
|
||||||
|
|
||||||
|
typedef struct ssaValueTypeName {
|
||||||
|
Type * type;
|
||||||
|
String name;
|
||||||
|
} ssaValueTypeName;
|
||||||
|
|
||||||
|
typedef struct ssaValueGlobal {
|
||||||
|
Entity * entity;
|
||||||
|
Type * type;
|
||||||
|
ssaValue * value;
|
||||||
|
ssaValueArray referrers;
|
||||||
|
bool is_constant;
|
||||||
|
bool is_private;
|
||||||
|
bool is_thread_local;
|
||||||
|
bool is_unnamed_addr;
|
||||||
|
} ssaValueGlobal;
|
||||||
|
|
||||||
|
typedef struct ssaValueParam {
|
||||||
|
ssaProcedure *parent;
|
||||||
|
Entity * entity;
|
||||||
|
Type * type;
|
||||||
|
ssaValueArray referrers;
|
||||||
|
} ssaValueParam;
|
||||||
|
|
||||||
typedef struct ssaValue {
|
typedef struct ssaValue {
|
||||||
ssaValueKind kind;
|
ssaValueKind kind;
|
||||||
i32 index;
|
i32 index;
|
||||||
union {
|
union {
|
||||||
struct {
|
ssaValueConstant Constant;
|
||||||
Type * type;
|
ssaValueConstantSlice ConstantSlice;
|
||||||
ExactValue value;
|
ssaValueNil Nil;
|
||||||
} Constant;
|
ssaValueTypeName TypeName;
|
||||||
struct {
|
ssaValueGlobal Global;
|
||||||
Type * type;
|
ssaValueParam Param;
|
||||||
ssaValue *backing_array;
|
ssaProcedure Proc;
|
||||||
i64 count;
|
ssaBlock Block;
|
||||||
} ConstantSlice;
|
ssaInstr Instr;
|
||||||
struct {
|
|
||||||
Type *type;
|
|
||||||
} Nil;
|
|
||||||
struct {
|
|
||||||
Type * type;
|
|
||||||
String name;
|
|
||||||
} TypeName;
|
|
||||||
struct {
|
|
||||||
Entity * entity;
|
|
||||||
Type * type;
|
|
||||||
ssaValue * value;
|
|
||||||
ssaValueArray referrers;
|
|
||||||
bool is_constant;
|
|
||||||
bool is_private;
|
|
||||||
bool is_thread_local;
|
|
||||||
bool is_unnamed_addr;
|
|
||||||
} Global;
|
|
||||||
struct {
|
|
||||||
ssaProcedure * parent;
|
|
||||||
Entity * entity;
|
|
||||||
Type * type;
|
|
||||||
ssaValueArray referrers;
|
|
||||||
} Param;
|
|
||||||
ssaProcedure Proc;
|
|
||||||
ssaBlock Block;
|
|
||||||
ssaInstr Instr;
|
|
||||||
};
|
};
|
||||||
} ssaValue;
|
} ssaValue;
|
||||||
|
|
||||||
@@ -2547,14 +2518,14 @@ void ssa_gen_global_type_name(ssaModule *m, Entity *e, String name) {
|
|||||||
|
|
||||||
Type *bt = base_type(e->type);
|
Type *bt = base_type(e->type);
|
||||||
if (bt->kind == Type_Record) {
|
if (bt->kind == Type_Record) {
|
||||||
auto *s = &bt->Record;
|
TypeRecord *s = &bt->Record;
|
||||||
for (isize j = 0; j < s->other_field_count; j++) {
|
for (isize j = 0; j < s->other_field_count; j++) {
|
||||||
ssa_mangle_sub_type_name(m, s->other_fields[j], name);
|
ssa_mangle_sub_type_name(m, s->other_fields[j], name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_type_union(bt)) {
|
if (is_type_union(bt)) {
|
||||||
auto *s = &bt->Record;
|
TypeRecord *s = &bt->Record;
|
||||||
// NOTE(bill): Zeroth entry is null (for `match type` stmts)
|
// NOTE(bill): Zeroth entry is null (for `match type` stmts)
|
||||||
for (isize j = 1; j < s->field_count; j++) {
|
for (isize j = 1; j < s->field_count; j++) {
|
||||||
ssa_mangle_sub_type_name(m, s->fields[j], name);
|
ssa_mangle_sub_type_name(m, s->fields[j], name);
|
||||||
@@ -3135,7 +3106,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
ssaValue *value = ssa_build_expr(proc, ce->proc);
|
ssaValue *value = ssa_build_expr(proc, ce->proc);
|
||||||
Type *proc_type_ = base_type(ssa_type(value));
|
Type *proc_type_ = base_type(ssa_type(value));
|
||||||
GB_ASSERT(proc_type_->kind == Type_Proc);
|
GB_ASSERT(proc_type_->kind == Type_Proc);
|
||||||
auto *type = &proc_type_->Proc;
|
TypeProc *type = &proc_type_->Proc;
|
||||||
|
|
||||||
isize arg_index = 0;
|
isize arg_index = 0;
|
||||||
|
|
||||||
@@ -3167,7 +3138,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *pt = &type->params->Tuple;
|
TypeTuple *pt = &type->params->Tuple;
|
||||||
|
|
||||||
if (variadic) {
|
if (variadic) {
|
||||||
isize i = 0;
|
isize i = 0;
|
||||||
@@ -3213,7 +3184,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (args[0]->kind == ssaValue_Constant) {
|
if (args[0]->kind == ssaValue_Constant) {
|
||||||
auto *c = &args[0]->Constant;
|
ssaValueConstant *c = &args[0]->Constant;
|
||||||
gb_printf_err("%s %d\n", type_to_string(c->type), c->value.kind);
|
gb_printf_err("%s %d\n", type_to_string(c->type), c->value.kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3657,7 +3628,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
|
|
||||||
case Type_Record: {
|
case Type_Record: {
|
||||||
GB_ASSERT(is_type_struct(bt));
|
GB_ASSERT(is_type_struct(bt));
|
||||||
auto *st = &bt->Record;
|
TypeRecord *st = &bt->Record;
|
||||||
if (cl->elems.count > 0) {
|
if (cl->elems.count > 0) {
|
||||||
ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
|
ssa_emit_store(proc, v, ssa_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
|
||||||
for_array(field_index, cl->elems) {
|
for_array(field_index, cl->elems) {
|
||||||
@@ -4121,7 +4092,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
|
|||||||
case_ast_node(rs, ReturnStmt, node);
|
case_ast_node(rs, ReturnStmt, node);
|
||||||
ssa_emit_comment(proc, str_lit("ReturnStmt"));
|
ssa_emit_comment(proc, str_lit("ReturnStmt"));
|
||||||
ssaValue *v = NULL;
|
ssaValue *v = NULL;
|
||||||
auto *return_type_tuple = &proc->type->Proc.results->Tuple;
|
TypeTuple *return_type_tuple = &proc->type->Proc.results->Tuple;
|
||||||
isize return_count = proc->type->Proc.result_count;
|
isize return_count = proc->type->Proc.result_count;
|
||||||
if (return_count == 0) {
|
if (return_count == 0) {
|
||||||
// No return values
|
// No return values
|
||||||
@@ -4569,7 +4540,7 @@ void ssa_begin_procedure_body(ssaProcedure *proc) {
|
|||||||
proc->curr_block = proc->entry_block;
|
proc->curr_block = proc->entry_block;
|
||||||
|
|
||||||
if (proc->type->Proc.params != NULL) {
|
if (proc->type->Proc.params != NULL) {
|
||||||
auto *params = &proc->type->Proc.params->Tuple;
|
TypeTuple *params = &proc->type->Proc.params->Tuple;
|
||||||
for (isize i = 0; i < params->variable_count; i++) {
|
for (isize i = 0; i < params->variable_count; i++) {
|
||||||
Entity *e = params->variables[i];
|
Entity *e = params->variables[i];
|
||||||
ssaValue *param = ssa_add_param(proc, e);
|
ssaValue *param = ssa_add_param(proc, e);
|
||||||
@@ -4938,7 +4909,7 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Entity_Procedure: {
|
case Entity_Procedure: {
|
||||||
auto *pd = &decl->proc_decl->ProcDecl;
|
AstNodeProcDecl *pd = &decl->proc_decl->ProcDecl;
|
||||||
String original_name = name;
|
String original_name = name;
|
||||||
AstNode *body = pd->body;
|
AstNode *body = pd->body;
|
||||||
if (pd->tags & ProcTag_foreign) {
|
if (pd->tags & ProcTag_foreign) {
|
||||||
|
|||||||
+2
-2
@@ -149,7 +149,7 @@ void ssa_remove_pred(ssaBlock *b, ssaBlock *p) {
|
|||||||
if (pred != p) {
|
if (pred != p) {
|
||||||
b->preds.e[i] = b->preds.e[j];
|
b->preds.e[i] = b->preds.e[j];
|
||||||
for_array(k, phis) {
|
for_array(k, phis) {
|
||||||
auto *phi = &phis.e[k]->Instr.Phi;
|
ssaInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||||
phi->edges.e[i] = phi->edges.e[j];
|
phi->edges.e[i] = phi->edges.e[j];
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
@@ -157,7 +157,7 @@ void ssa_remove_pred(ssaBlock *b, ssaBlock *p) {
|
|||||||
}
|
}
|
||||||
b->preds.count = i;
|
b->preds.count = i;
|
||||||
for_array(k, phis) {
|
for_array(k, phis) {
|
||||||
auto *phi = &phis.e[k]->Instr.Phi;
|
ssaInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||||
phi->edges.count = i;
|
phi->edges.count = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+21
-20
@@ -268,7 +268,7 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
|
|||||||
ssa_print_type(f, m, t->Proc.results);
|
ssa_print_type(f, m, t->Proc.results);
|
||||||
}
|
}
|
||||||
ssa_fprintf(f, " (");
|
ssa_fprintf(f, " (");
|
||||||
auto *params = &t->Proc.params->Tuple;
|
TypeTuple *params = &t->Proc.params->Tuple;
|
||||||
for (isize i = 0; i < t->Proc.param_count; i++) {
|
for (isize i = 0; i < t->Proc.param_count; i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
ssa_fprintf(f, ", ");
|
ssa_fprintf(f, ", ");
|
||||||
@@ -580,7 +580,7 @@ void ssa_print_value(ssaFileBuffer *f, ssaModule *m, ssaValue *value, Type *type
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ssaValue_ConstantSlice: {
|
case ssaValue_ConstantSlice: {
|
||||||
auto *cs = &value->ConstantSlice;
|
ssaValueConstantSlice *cs = &value->ConstantSlice;
|
||||||
if (cs->backing_array == NULL || cs->count == 0) {
|
if (cs->backing_array == NULL || cs->count == 0) {
|
||||||
ssa_fprintf(f, "zeroinitializer");
|
ssa_fprintf(f, "zeroinitializer");
|
||||||
} else {
|
} else {
|
||||||
@@ -835,7 +835,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Return: {
|
case ssaInstr_Return: {
|
||||||
auto *ret = &instr->Return;
|
ssaInstrReturn *ret = &instr->Return;
|
||||||
ssa_fprintf(f, "ret ");
|
ssa_fprintf(f, "ret ");
|
||||||
if (ret->value == NULL) {
|
if (ret->value == NULL) {
|
||||||
ssa_fprintf(f, "void");
|
ssa_fprintf(f, "void");
|
||||||
@@ -851,7 +851,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Conv: {
|
case ssaInstr_Conv: {
|
||||||
auto *c = &instr->Conv;
|
ssaInstrConv *c = &instr->Conv;
|
||||||
ssa_fprintf(f, "%%%d = %.*s ", value->index, LIT(ssa_conv_strings[c->kind]));
|
ssa_fprintf(f, "%%%d = %.*s ", value->index, LIT(ssa_conv_strings[c->kind]));
|
||||||
ssa_print_type(f, m, c->from);
|
ssa_print_type(f, m, c->from);
|
||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
@@ -867,7 +867,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_BinaryOp: {
|
case ssaInstr_BinaryOp: {
|
||||||
auto *bo = &value->Instr.BinaryOp;
|
ssaInstrBinaryOp *bo = &value->Instr.BinaryOp;
|
||||||
Type *type = base_type(ssa_type(bo->left));
|
Type *type = base_type(ssa_type(bo->left));
|
||||||
Type *elem_type = type;
|
Type *elem_type = type;
|
||||||
while (elem_type->kind == Type_Vector) {
|
while (elem_type->kind == Type_Vector) {
|
||||||
@@ -975,7 +975,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_Call: {
|
case ssaInstr_Call: {
|
||||||
auto *call = &instr->Call;
|
ssaInstrCall *call = &instr->Call;
|
||||||
Type *result_type = call->type;
|
Type *result_type = call->type;
|
||||||
if (result_type) {
|
if (result_type) {
|
||||||
ssa_fprintf(f, "%%%d = ", value->index);
|
ssa_fprintf(f, "%%%d = ", value->index);
|
||||||
@@ -994,7 +994,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
if (call->arg_count > 0) {
|
if (call->arg_count > 0) {
|
||||||
Type *proc_type = base_type(ssa_type(call->value));
|
Type *proc_type = base_type(ssa_type(call->value));
|
||||||
GB_ASSERT(proc_type->kind == Type_Proc);
|
GB_ASSERT(proc_type->kind == Type_Proc);
|
||||||
auto *params = &proc_type->Proc.params->Tuple;
|
TypeTuple *params = &proc_type->Proc.params->Tuple;
|
||||||
for (isize i = 0; i < call->arg_count; i++) {
|
for (isize i = 0; i < call->arg_count; i++) {
|
||||||
Entity *e = params->variables[i];
|
Entity *e = params->variables[i];
|
||||||
GB_ASSERT(e != NULL);
|
GB_ASSERT(e != NULL);
|
||||||
@@ -1042,7 +1042,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_VectorInsertElement: {
|
case ssaInstr_VectorInsertElement: {
|
||||||
auto *ie = &instr->VectorInsertElement;
|
ssaInstrVectorInsertElement *ie = &instr->VectorInsertElement;
|
||||||
Type *vt = ssa_type(ie->vector);
|
Type *vt = ssa_type(ie->vector);
|
||||||
ssa_fprintf(f, "%%%d = insertelement ", value->index);
|
ssa_fprintf(f, "%%%d = insertelement ", value->index);
|
||||||
|
|
||||||
@@ -1064,7 +1064,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_VectorShuffle: {
|
case ssaInstr_VectorShuffle: {
|
||||||
auto *sv = &instr->VectorShuffle;
|
ssaInstrVectorShuffle *sv = &instr->VectorShuffle;
|
||||||
Type *vt = ssa_type(sv->vector);
|
Type *vt = ssa_type(sv->vector);
|
||||||
ssa_fprintf(f, "%%%d = shufflevector ", value->index);
|
ssa_fprintf(f, "%%%d = shufflevector ", value->index);
|
||||||
|
|
||||||
@@ -1090,7 +1090,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_BoundsCheck: {
|
case ssaInstr_BoundsCheck: {
|
||||||
auto *bc = &instr->BoundsCheck;
|
ssaInstrBoundsCheck *bc = &instr->BoundsCheck;
|
||||||
ssa_fprintf(f, "call void ");
|
ssa_fprintf(f, "call void ");
|
||||||
ssa_print_encoded_global(f, str_lit("__bounds_check_error"), false);
|
ssa_print_encoded_global(f, str_lit("__bounds_check_error"), false);
|
||||||
ssa_fprintf(f, "(");
|
ssa_fprintf(f, "(");
|
||||||
@@ -1120,7 +1120,7 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case ssaInstr_SliceBoundsCheck: {
|
case ssaInstr_SliceBoundsCheck: {
|
||||||
auto *bc = &instr->SliceBoundsCheck;
|
ssaInstrSliceBoundsCheck *bc = &instr->SliceBoundsCheck;
|
||||||
ssa_fprintf(f, "call void ");
|
ssa_fprintf(f, "call void ");
|
||||||
if (bc->is_substring) {
|
if (bc->is_substring) {
|
||||||
ssa_print_encoded_global(f, str_lit("__substring_expr_error"), false);
|
ssa_print_encoded_global(f, str_lit("__substring_expr_error"), false);
|
||||||
@@ -1188,7 +1188,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
|
|||||||
ssa_fprintf(f, "cc 65 ");
|
ssa_fprintf(f, "cc 65 ");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *proc_type = &proc->type->Proc;
|
TypeProc *proc_type = &proc->type->Proc;
|
||||||
|
|
||||||
if (proc_type->result_count == 0) {
|
if (proc_type->result_count == 0) {
|
||||||
ssa_fprintf(f, "void");
|
ssa_fprintf(f, "void");
|
||||||
@@ -1201,7 +1201,7 @@ void ssa_print_proc(ssaFileBuffer *f, ssaModule *m, ssaProcedure *proc) {
|
|||||||
ssa_fprintf(f, "(");
|
ssa_fprintf(f, "(");
|
||||||
|
|
||||||
if (proc_type->param_count > 0) {
|
if (proc_type->param_count > 0) {
|
||||||
auto *params = &proc_type->params->Tuple;
|
TypeTuple *params = &proc_type->params->Tuple;
|
||||||
for (isize i = 0; i < params->variable_count; i++) {
|
for (isize i = 0; i < params->variable_count; i++) {
|
||||||
Entity *e = params->variables[i];
|
Entity *e = params->variables[i];
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
@@ -1296,7 +1296,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
|||||||
|
|
||||||
|
|
||||||
for_array(member_index, m->members.entries) {
|
for_array(member_index, m->members.entries) {
|
||||||
auto *entry = &m->members.entries.e[member_index];
|
MapSsaValueEntry *entry = &m->members.entries.e[member_index];
|
||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
if (v->kind != ssaValue_TypeName) {
|
if (v->kind != ssaValue_TypeName) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1307,7 +1307,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
|||||||
ssa_fprintf(f, "\n");
|
ssa_fprintf(f, "\n");
|
||||||
|
|
||||||
for_array(member_index, m->members.entries) {
|
for_array(member_index, m->members.entries) {
|
||||||
auto *entry = &m->members.entries.e[member_index];
|
MapSsaValueEntry *entry = &m->members.entries.e[member_index];
|
||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
if (v->kind != ssaValue_Proc) {
|
if (v->kind != ssaValue_Proc) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1318,7 +1318,7 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(member_index, m->members.entries) {
|
for_array(member_index, m->members.entries) {
|
||||||
auto *entry = &m->members.entries.e[member_index];
|
MapSsaValueEntry *entry = &m->members.entries.e[member_index];
|
||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
if (v->kind != ssaValue_Proc) {
|
if (v->kind != ssaValue_Proc) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1330,12 +1330,12 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
|||||||
|
|
||||||
|
|
||||||
for_array(member_index, m->members.entries) {
|
for_array(member_index, m->members.entries) {
|
||||||
auto *entry = &m->members.entries.e[member_index];
|
MapSsaValueEntry *entry = &m->members.entries.e[member_index];
|
||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
if (v->kind != ssaValue_Global) {
|
if (v->kind != ssaValue_Global) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto *g = &v->Global;
|
ssaValueGlobal *g = &v->Global;
|
||||||
Scope *scope = g->entity->scope;
|
Scope *scope = g->entity->scope;
|
||||||
bool in_global_scope = false;
|
bool in_global_scope = false;
|
||||||
if (scope != NULL) {
|
if (scope != NULL) {
|
||||||
@@ -1371,12 +1371,13 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (m->generate_debug_info) {
|
if (m->generate_debug_info) {
|
||||||
ssa_fprintf(f, "\n");
|
ssa_fprintf(f, "\n");
|
||||||
ssa_fprintf(f, "!llvm.dbg.cu = !{!0}\n");
|
ssa_fprintf(f, "!llvm.dbg.cu = !{!0}\n");
|
||||||
|
|
||||||
for_array(di_index, m->debug_info.entries) {
|
for_array(di_index, m->debug_info.entries) {
|
||||||
auto *entry = &m->debug_info.entries.e[di_index];
|
MapSsaDebugInfoEntry *entry = &m->debug_info.entries.e[di_index];
|
||||||
ssaDebugInfo *di = entry->value;
|
ssaDebugInfo *di = entry->value;
|
||||||
ssa_fprintf(f, "!%d = ", di->id);
|
ssa_fprintf(f, "!%d = ", di->id);
|
||||||
|
|
||||||
@@ -1433,6 +1434,6 @@ void ssa_print_llvm_ir(ssaGen *ssa) {
|
|||||||
ssa_fprintf(f, "\n");
|
ssa_fprintf(f, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
ssa_file_buffer_destroy(f);
|
ssa_file_buffer_destroy(f);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user