mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 08:08:50 +00:00
Add string_set.cpp; Code clean up
This commit is contained in:
+71
-7
@@ -459,8 +459,6 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
|
|
||||||
bool is_foreign = e->Procedure.is_foreign;
|
bool is_foreign = e->Procedure.is_foreign;
|
||||||
bool is_export = e->Procedure.is_export;
|
bool is_export = e->Procedure.is_export;
|
||||||
bool is_inline = (pl->tags & ProcTag_inline) != 0;
|
|
||||||
bool is_no_inline = (pl->tags & ProcTag_no_inline) != 0;
|
|
||||||
bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
|
bool is_require_results = (pl->tags & ProcTag_require_results) != 0;
|
||||||
|
|
||||||
String link_name = {};
|
String link_name = {};
|
||||||
@@ -513,6 +511,9 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
if (name == "link_name") {
|
if (name == "link_name") {
|
||||||
if (ev.kind == ExactValue_String) {
|
if (ev.kind == ExactValue_String) {
|
||||||
link_name = ev.value_string;
|
link_name = ev.value_string;
|
||||||
|
if (!is_foreign_name_valid(link_name)) {
|
||||||
|
error(elem, "Invalid link name: %.*s", LIT(link_name));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
||||||
}
|
}
|
||||||
@@ -548,10 +549,6 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_inline && is_no_inline) {
|
|
||||||
error(pl->type, "You cannot apply both `inline` and `no_inline` to a procedure");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_foreign && is_export) {
|
if (is_foreign && is_export) {
|
||||||
error(pl->type, "A foreign procedure cannot have an `export` tag");
|
error(pl->type, "A foreign procedure cannot have an `export` tag");
|
||||||
}
|
}
|
||||||
@@ -673,9 +670,69 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
}
|
}
|
||||||
e->flags |= EntityFlag_Visited;
|
e->flags |= EntityFlag_Visited;
|
||||||
|
|
||||||
|
|
||||||
|
String link_name = {};
|
||||||
|
|
||||||
DeclInfo *decl = decl_info_of_entity(&c->info, e);
|
DeclInfo *decl = decl_info_of_entity(&c->info, e);
|
||||||
if (decl != nullptr && decl->attributes.count > 0) {
|
if (decl != nullptr && decl->attributes.count > 0) {
|
||||||
error(decl->attributes[0], "Attributes are not allowed on variable declarations, yet");
|
StringSet set = {};
|
||||||
|
string_set_init(&set, heap_allocator());
|
||||||
|
defer (string_set_destroy(&set));
|
||||||
|
|
||||||
|
for_array(i, decl->attributes) {
|
||||||
|
AstNode *attr = decl->attributes[i];
|
||||||
|
if (attr->kind != AstNode_Attribute) continue;
|
||||||
|
for_array(j, attr->Attribute.elems) {
|
||||||
|
AstNode *elem = attr->Attribute.elems[j];
|
||||||
|
String name = {};
|
||||||
|
AstNode *value = nullptr;
|
||||||
|
|
||||||
|
switch (elem->kind) {
|
||||||
|
case_ast_node(i, Ident, elem);
|
||||||
|
name = i->token.string;
|
||||||
|
case_end;
|
||||||
|
case_ast_node(fv, FieldValue, elem);
|
||||||
|
GB_ASSERT(fv->field->kind == AstNode_Ident);
|
||||||
|
name = fv->field->Ident.token.string;
|
||||||
|
value = fv->value;
|
||||||
|
case_end;
|
||||||
|
default:
|
||||||
|
error(elem, "Invalid attribute element");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExactValue ev = {};
|
||||||
|
if (value != nullptr) {
|
||||||
|
Operand op = {};
|
||||||
|
check_expr(c, &op, value);
|
||||||
|
if (op.mode != Addressing_Constant) {
|
||||||
|
error(value, "An attribute element must be constant");
|
||||||
|
} else {
|
||||||
|
ev = op.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string_set_exists(&set, name)) {
|
||||||
|
error(elem, "Previous declaration of `%.*s`", LIT(name));
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
string_set_add(&set, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == "link_name") {
|
||||||
|
if (ev.kind == ExactValue_String) {
|
||||||
|
link_name = ev.value_string;
|
||||||
|
if (!is_foreign_name_valid(link_name)) {
|
||||||
|
error(elem, "Invalid link name: %.*s", LIT(link_name));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(elem, "Expected a string value for `%.*s`", LIT(name));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error(elem, "Unknown attribute element name `%.*s`", LIT(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String context_name = str_lit("variable declaration");
|
String context_name = str_lit("variable declaration");
|
||||||
@@ -704,8 +761,15 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
}
|
}
|
||||||
init_entity_foreign_library(c, e);
|
init_entity_foreign_library(c, e);
|
||||||
}
|
}
|
||||||
|
if (link_name.len > 0) {
|
||||||
|
e->Variable.link_name = link_name;
|
||||||
|
}
|
||||||
|
|
||||||
if (e->Variable.is_foreign || e->Variable.is_export) {
|
if (e->Variable.is_foreign || e->Variable.is_export) {
|
||||||
String name = e->token.string;
|
String name = e->token.string;
|
||||||
|
if (link_name.len > 0) {
|
||||||
|
name = link_name;
|
||||||
|
}
|
||||||
auto *fp = &c->info.foreigns;
|
auto *fp = &c->info.foreigns;
|
||||||
HashKey key = hash_string(name);
|
HashKey key = hash_string(name);
|
||||||
Entity **found = map_get(fp, key);
|
Entity **found = map_get(fp, key);
|
||||||
|
|||||||
+1
-1
@@ -1670,7 +1670,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
CheckerContext prev_context = c->context;
|
CheckerContext prev_context = c->context;
|
||||||
if (ok) {
|
if (ok) {
|
||||||
c->context.curr_foreign_library = foreign_library;
|
c->context.curr_foreign_library = foreign_library;
|
||||||
c->context.default_foreign_cc = ProcCC_C;
|
c->context.default_foreign_cc = ProcCC_CDecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
check_foreign_block_decl_attributes(c, fb);
|
check_foreign_block_decl_attributes(c, fb);
|
||||||
|
|||||||
+4
-8
@@ -1890,7 +1890,7 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
|
|||||||
|
|
||||||
ProcCallingConvention cc = pt->calling_convention;
|
ProcCallingConvention cc = pt->calling_convention;
|
||||||
if (cc == ProcCC_ForeignBlockDefault) {
|
if (cc == ProcCC_ForeignBlockDefault) {
|
||||||
cc = ProcCC_C;
|
cc = ProcCC_CDecl;
|
||||||
if (c->context.default_foreign_cc > 0) {
|
if (c->context.default_foreign_cc > 0) {
|
||||||
cc = c->context.default_foreign_cc;
|
cc = c->context.default_foreign_cc;
|
||||||
}
|
}
|
||||||
@@ -1911,14 +1911,10 @@ bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
|
|||||||
if (param_count > 0) {
|
if (param_count > 0) {
|
||||||
Entity *end = params->Tuple.variables[param_count-1];
|
Entity *end = params->Tuple.variables[param_count-1];
|
||||||
if (end->flags&EntityFlag_CVarArg) {
|
if (end->flags&EntityFlag_CVarArg) {
|
||||||
if (cc == ProcCC_Odin) {
|
if (cc == ProcCC_StdCall || cc == ProcCC_CDecl) {
|
||||||
error(end->token, "Odin calling convention does not support #c_vararg");
|
|
||||||
} else if (cc == ProcCC_Contextless) {
|
|
||||||
error(end->token, "Odin's contextless calling convention does not support #c_vararg");
|
|
||||||
} else if (cc == ProcCC_Fast) {
|
|
||||||
error(end->token, "Fast calling convention does not support #c_vararg");
|
|
||||||
} else {
|
|
||||||
type->Proc.c_vararg = true;
|
type->Proc.c_vararg = true;
|
||||||
|
} else {
|
||||||
|
error(end->token, "Calling convention does not support #c_vararg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -2126,7 +2126,7 @@ void check_collect_value_decl(Checker *c, AstNode *decl) {
|
|||||||
GB_ASSERT(pl->type->kind == AstNode_ProcType);
|
GB_ASSERT(pl->type->kind == AstNode_ProcType);
|
||||||
auto cc = pl->type->ProcType.calling_convention;
|
auto cc = pl->type->ProcType.calling_convention;
|
||||||
if (cc == ProcCC_ForeignBlockDefault) {
|
if (cc == ProcCC_ForeignBlockDefault) {
|
||||||
cc = ProcCC_C;
|
cc = ProcCC_CDecl;
|
||||||
if (c->context.default_foreign_cc > 0) {
|
if (c->context.default_foreign_cc > 0) {
|
||||||
cc = c->context.default_foreign_cc;
|
cc = c->context.default_foreign_cc;
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-5
@@ -117,6 +117,7 @@ struct irProcedure {
|
|||||||
AstNode * type_expr;
|
AstNode * type_expr;
|
||||||
AstNode * body;
|
AstNode * body;
|
||||||
u64 tags;
|
u64 tags;
|
||||||
|
ProcInlining inlining;
|
||||||
bool is_foreign;
|
bool is_foreign;
|
||||||
bool is_export;
|
bool is_export;
|
||||||
bool is_entry_point;
|
bool is_entry_point;
|
||||||
@@ -3695,6 +3696,7 @@ irValue *ir_gen_anonymous_proc_lit(irModule *m, String prefix_name, AstNode *exp
|
|||||||
m, nullptr, type, pl->type, pl->body, name);
|
m, nullptr, type, pl->type, pl->body, name);
|
||||||
|
|
||||||
value->Proc.tags = pl->tags;
|
value->Proc.tags = pl->tags;
|
||||||
|
value->Proc.inlining = pl->inlining;
|
||||||
value->Proc.parent = proc;
|
value->Proc.parent = proc;
|
||||||
|
|
||||||
array_add(&m->procs_to_generate, value);
|
array_add(&m->procs_to_generate, value);
|
||||||
@@ -5902,6 +5904,7 @@ void ir_build_poly_proc(irProcedure *proc, AstNodeProcLit *pd, Entity *e) {
|
|||||||
proc->module, e, e->type, pd->type, pd->body, name);
|
proc->module, e, e->type, pd->type, pd->body, name);
|
||||||
|
|
||||||
value->Proc.tags = pd->tags;
|
value->Proc.tags = pd->tags;
|
||||||
|
value->Proc.inlining = pd->inlining;
|
||||||
value->Proc.parent = proc;
|
value->Proc.parent = proc;
|
||||||
|
|
||||||
ir_module_add_value(proc->module, e, value);
|
ir_module_add_value(proc->module, e, value);
|
||||||
@@ -5987,6 +5990,7 @@ void ir_build_constant_value_decl(irProcedure *proc, AstNodeValueDecl *vd) {
|
|||||||
proc->module, e, e->type, pl->type, pl->body, name);
|
proc->module, e, e->type, pl->type, pl->body, name);
|
||||||
|
|
||||||
value->Proc.tags = pl->tags;
|
value->Proc.tags = pl->tags;
|
||||||
|
value->Proc.inlining = pl->inlining;
|
||||||
|
|
||||||
ir_module_add_value(proc->module, e, value);
|
ir_module_add_value(proc->module, e, value);
|
||||||
ir_build_proc(value, proc);
|
ir_build_proc(value, proc);
|
||||||
@@ -8295,6 +8299,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
irValue *p = ir_value_procedure(a, m, e, e->type, type_expr, body, name);
|
irValue *p = ir_value_procedure(a, m, e, e->type, type_expr, body, name);
|
||||||
p->Proc.tags = pl->tags;
|
p->Proc.tags = pl->tags;
|
||||||
|
p->Proc.inlining = pl->inlining;
|
||||||
|
|
||||||
ir_module_add_value(m, e, p);
|
ir_module_add_value(m, e, p);
|
||||||
HashKey hash_name = hash_string(name);
|
HashKey hash_name = hash_string(name);
|
||||||
@@ -8363,7 +8368,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
Type *proc_type = make_type_proc(a, proc_scope,
|
Type *proc_type = make_type_proc(a, proc_scope,
|
||||||
proc_params, 3,
|
proc_params, 3,
|
||||||
proc_results, 1, false, ProcCC_Std);
|
proc_results, 1, false, ProcCC_StdCall);
|
||||||
|
|
||||||
// TODO(bill): make this more robust
|
// TODO(bill): make this more robust
|
||||||
proc_type->Proc.abi_compat_params = gb_alloc_array(a, Type *, proc_params->Tuple.variables.count);
|
proc_type->Proc.abi_compat_params = gb_alloc_array(a, Type *, proc_params->Tuple.variables.count);
|
||||||
@@ -8380,7 +8385,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
map_set(&m->members, hash_string(name), p);
|
map_set(&m->members, hash_string(name), p);
|
||||||
|
|
||||||
irProcedure *proc = &p->Proc;
|
irProcedure *proc = &p->Proc;
|
||||||
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea?
|
||||||
proc->is_entry_point = true;
|
proc->is_entry_point = true;
|
||||||
e->Procedure.link_name = name;
|
e->Procedure.link_name = name;
|
||||||
|
|
||||||
@@ -8434,7 +8439,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
Type *proc_type = make_type_proc(a, proc_scope,
|
Type *proc_type = make_type_proc(a, proc_scope,
|
||||||
proc_params, 2,
|
proc_params, 2,
|
||||||
proc_results, 1, false, ProcCC_C);
|
proc_results, 1, false, ProcCC_CDecl);
|
||||||
|
|
||||||
// TODO(bill): make this more robust
|
// TODO(bill): make this more robust
|
||||||
proc_type->Proc.abi_compat_params = gb_alloc_array(a, Type *, proc_params->Tuple.variables.count);
|
proc_type->Proc.abi_compat_params = gb_alloc_array(a, Type *, proc_params->Tuple.variables.count);
|
||||||
@@ -8451,7 +8456,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
map_set(&m->members, hash_string(name), p);
|
map_set(&m->members, hash_string(name), p);
|
||||||
|
|
||||||
irProcedure *proc = &p->Proc;
|
irProcedure *proc = &p->Proc;
|
||||||
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea?
|
||||||
proc->is_entry_point = true;
|
proc->is_entry_point = true;
|
||||||
e->Procedure.link_name = name;
|
e->Procedure.link_name = name;
|
||||||
|
|
||||||
@@ -8543,7 +8548,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
|
|
||||||
|
|
||||||
irProcedure *proc = &p->Proc;
|
irProcedure *proc = &p->Proc;
|
||||||
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
proc->inlining = ProcInlining_no_inline; // TODO(bill): is no_inline a good idea?
|
||||||
|
|
||||||
ir_begin_procedure_body(proc);
|
ir_begin_procedure_body(proc);
|
||||||
|
|
||||||
|
|||||||
+9
-8
@@ -882,9 +882,9 @@ void ir_print_calling_convention(irFileBuffer *f, irModule *m, ProcCallingConven
|
|||||||
switch (cc) {
|
switch (cc) {
|
||||||
case ProcCC_Odin: ir_write_string(f, ""); break;
|
case ProcCC_Odin: ir_write_string(f, ""); break;
|
||||||
case ProcCC_Contextless: ir_write_string(f, ""); break;
|
case ProcCC_Contextless: ir_write_string(f, ""); break;
|
||||||
case ProcCC_C: ir_write_string(f, "ccc "); break;
|
case ProcCC_CDecl: ir_write_string(f, "ccc "); break;
|
||||||
case ProcCC_Std: ir_write_string(f, "cc 64 "); break;
|
case ProcCC_StdCall: ir_write_string(f, "cc 64 "); break;
|
||||||
case ProcCC_Fast: ir_write_string(f, "cc 65 "); break;
|
case ProcCC_FastCall: ir_write_string(f, "cc 65 "); break;
|
||||||
default: GB_PANIC("unknown calling convention: %d", cc);
|
default: GB_PANIC("unknown calling convention: %d", cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1751,14 +1751,15 @@ void ir_print_proc(irFileBuffer *f, irModule *m, irProcedure *proc) {
|
|||||||
|
|
||||||
ir_write_string(f, ") ");
|
ir_write_string(f, ") ");
|
||||||
|
|
||||||
if (proc->tags & ProcTag_inline) {
|
switch (proc->inlining) {
|
||||||
ir_write_string(f, "alwaysinline ");
|
case ProcInlining_no_inline:
|
||||||
}
|
|
||||||
if (proc->tags & ProcTag_no_inline) {
|
|
||||||
ir_write_string(f, "noinline ");
|
ir_write_string(f, "noinline ");
|
||||||
|
break;
|
||||||
|
case ProcInlining_inline:
|
||||||
|
ir_write_string(f, "alwaysinline ");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (proc->entity != nullptr) {
|
if (proc->entity != nullptr) {
|
||||||
if (proc->body != nullptr) {
|
if (proc->body != nullptr) {
|
||||||
irDebugInfo **di_ = map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
irDebugInfo **di_ = map_get(&proc->module->debug_info, hash_pointer(proc->entity));
|
||||||
|
|||||||
+36
-28
@@ -88,28 +88,29 @@ struct Parser {
|
|||||||
gbMutex file_decl_mutex;
|
gbMutex file_decl_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ProcInlining {
|
||||||
|
ProcInlining_none = 0,
|
||||||
|
ProcInlining_inline = 1,
|
||||||
|
ProcInlining_no_inline = 2,
|
||||||
|
};
|
||||||
|
|
||||||
enum ProcTag {
|
enum ProcTag {
|
||||||
ProcTag_bounds_check = 1<<0,
|
ProcTag_bounds_check = 1<<0,
|
||||||
ProcTag_no_bounds_check = 1<<1,
|
ProcTag_no_bounds_check = 1<<1,
|
||||||
|
|
||||||
|
|
||||||
ProcTag_require_results = 1<<4,
|
ProcTag_require_results = 1<<4,
|
||||||
|
|
||||||
ProcTag_link_name = 1<<11,
|
|
||||||
ProcTag_inline = 1<<12,
|
|
||||||
ProcTag_no_inline = 1<<13,
|
|
||||||
|
|
||||||
// ProcTag_dll_import = 1<<15,
|
|
||||||
// ProcTag_dll_export = 1<<16,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ProcCallingConvention {
|
enum ProcCallingConvention {
|
||||||
ProcCC_Invalid = 0,
|
ProcCC_Invalid = 0,
|
||||||
ProcCC_Odin = 1,
|
ProcCC_Odin,
|
||||||
ProcCC_Contextless = 2,
|
ProcCC_Contextless,
|
||||||
ProcCC_C = 3,
|
ProcCC_CDecl,
|
||||||
ProcCC_Std = 4,
|
ProcCC_StdCall,
|
||||||
ProcCC_Fast = 5,
|
ProcCC_FastCall,
|
||||||
|
|
||||||
|
// TODO(bill): Add extra calling conventions
|
||||||
|
// ProcCC_VectorCall,
|
||||||
|
// ProcCC_ClrCall,
|
||||||
|
|
||||||
ProcCC_ForeignBlockDefault = -1,
|
ProcCC_ForeignBlockDefault = -1,
|
||||||
};
|
};
|
||||||
@@ -172,6 +173,7 @@ Array<AstNode *> make_ast_node_array(AstFile *f, isize init_capacity = 8) {
|
|||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
|
ProcInlining inlining; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(CompoundLit, "compound literal", struct { \
|
AST_NODE_KIND(CompoundLit, "compound literal", struct { \
|
||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
@@ -2275,11 +2277,20 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
syntax_error(expr, "%.*s must be followed by a procedure literal, got %.*s", LIT(token.string), LIT(ast_node_strings[expr->kind]));
|
syntax_error(expr, "%.*s must be followed by a procedure literal, got %.*s", LIT(token.string), LIT(ast_node_strings[expr->kind]));
|
||||||
return ast_bad_expr(f, token, f->curr_token);
|
return ast_bad_expr(f, token, f->curr_token);
|
||||||
}
|
}
|
||||||
|
ProcInlining pi = ProcInlining_none;
|
||||||
if (token.kind == Token_inline) {
|
if (token.kind == Token_inline) {
|
||||||
expr->ProcLit.tags |= ProcTag_inline;
|
pi = ProcInlining_inline;
|
||||||
} else if (token.kind == Token_no_inline) {
|
} else if (token.kind == Token_no_inline) {
|
||||||
expr->ProcLit.tags |= ProcTag_no_inline;
|
pi = ProcInlining_no_inline;
|
||||||
}
|
}
|
||||||
|
if (pi != ProcInlining_none) {
|
||||||
|
if (expr->ProcLit.inlining != ProcInlining_none &&
|
||||||
|
expr->ProcLit.inlining != pi) {
|
||||||
|
syntax_error(expr, "You cannot apply both `inline` and `no_inline` to a procedure literal");
|
||||||
|
}
|
||||||
|
expr->ProcLit.inlining = pi;
|
||||||
|
}
|
||||||
|
|
||||||
return expr;
|
return expr;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -3255,17 +3266,14 @@ AstNode *parse_results(AstFile *f) {
|
|||||||
|
|
||||||
|
|
||||||
ProcCallingConvention string_to_calling_convention(String s) {
|
ProcCallingConvention string_to_calling_convention(String s) {
|
||||||
if (s == "odin") {
|
if (s == "odin") return ProcCC_Odin;
|
||||||
return ProcCC_Odin;
|
if (s == "contextless") return ProcCC_Contextless;
|
||||||
} else if (s == "contextless") {
|
if (s == "cdecl") return ProcCC_CDecl;
|
||||||
return ProcCC_Contextless;
|
if (s == "c") return ProcCC_CDecl;
|
||||||
} else if (s == "cdecl" || s == "c") {
|
if (s == "stdcall") return ProcCC_StdCall;
|
||||||
return ProcCC_C;
|
if (s == "std") return ProcCC_StdCall;
|
||||||
} else if (s == "stdcall" || s == "std") {
|
if (s == "fastcall") return ProcCC_FastCall;
|
||||||
return ProcCC_Std;
|
if (s == "fast") return ProcCC_FastCall;
|
||||||
} else if (s == "fastcall" || s == "fast") {
|
|
||||||
return ProcCC_Fast;
|
|
||||||
}
|
|
||||||
return ProcCC_Invalid;
|
return ProcCC_Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,184 @@
|
|||||||
|
struct StringSetFindResult {
|
||||||
|
isize hash_index;
|
||||||
|
isize entry_prev;
|
||||||
|
isize entry_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringSetEntry {
|
||||||
|
HashKey key;
|
||||||
|
isize next;
|
||||||
|
String value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct StringSet {
|
||||||
|
Array<isize> hashes;
|
||||||
|
Array<StringSetEntry> entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void string_set_init (StringSet *s, gbAllocator a, isize capacity = 16);
|
||||||
|
void string_set_destroy(StringSet *s);
|
||||||
|
void string_set_add (StringSet *s, String str);
|
||||||
|
bool string_set_exists (StringSet *s, String str);
|
||||||
|
void string_set_remove (StringSet *s, String str);
|
||||||
|
void string_set_clear (StringSet *s);
|
||||||
|
void string_set_grow (StringSet *s);
|
||||||
|
void string_set_rehash (StringSet *s, isize new_count);
|
||||||
|
|
||||||
|
|
||||||
|
gb_inline void string_set_init(StringSet *s, gbAllocator a, isize capacity) {
|
||||||
|
array_init(&s->hashes, a);
|
||||||
|
array_init(&s->entries, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline void string_set_destroy(StringSet *s) {
|
||||||
|
array_free(&s->entries);
|
||||||
|
array_free(&s->hashes);
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal isize string_set__add_entry(StringSet *s, HashKey key) {
|
||||||
|
StringSetEntry e = {};
|
||||||
|
e.key = key;
|
||||||
|
e.next = -1;
|
||||||
|
array_add(&s->entries, e);
|
||||||
|
return s->entries.count-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal StringSetFindResult string_set__find(StringSet *s, HashKey key) {
|
||||||
|
StringSetFindResult fr = {-1, -1, -1};
|
||||||
|
if (s->hashes.count > 0) {
|
||||||
|
// fr.hash_index = u128_to_i64(key.key % u128_from_i64(s->hashes.count));
|
||||||
|
fr.hash_index = key.key % s->hashes.count;
|
||||||
|
fr.entry_index = s->hashes[fr.hash_index];
|
||||||
|
while (fr.entry_index >= 0) {
|
||||||
|
if (hash_key_equal(s->entries[fr.entry_index].key, key)) {
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
fr.entry_prev = fr.entry_index;
|
||||||
|
fr.entry_index = s->entries[fr.entry_index].next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal StringSetFindResult string_set__find_from_entry(StringSet *s, StringSetEntry *e) {
|
||||||
|
StringSetFindResult fr = {-1, -1, -1};
|
||||||
|
if (s->hashes.count > 0) {
|
||||||
|
fr.hash_index = e->key.key % s->hashes.count;
|
||||||
|
fr.entry_index = s->hashes[fr.hash_index];
|
||||||
|
while (fr.entry_index >= 0) {
|
||||||
|
if (&s->entries[fr.entry_index] == e) {
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
fr.entry_prev = fr.entry_index;
|
||||||
|
fr.entry_index = s->entries[fr.entry_index].next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_internal b32 string_set__full(StringSet *s) {
|
||||||
|
return 0.75f * s->hashes.count <= s->entries.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline void string_set_grow(StringSet *s) {
|
||||||
|
isize new_count = ARRAY_GROW_FORMULA(s->entries.count);
|
||||||
|
string_set_rehash(s, new_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void string_set_rehash(StringSet *s, isize new_count) {
|
||||||
|
isize i, j;
|
||||||
|
StringSet ns = {};
|
||||||
|
string_set_init(&ns, s->hashes.allocator);
|
||||||
|
array_resize(&ns.hashes, new_count);
|
||||||
|
array_reserve(&ns.entries, s->entries.count);
|
||||||
|
for (i = 0; i < new_count; i++) {
|
||||||
|
ns.hashes[i] = -1;
|
||||||
|
}
|
||||||
|
for (i = 0; i < s->entries.count; i++) {
|
||||||
|
StringSetEntry *e = &s->entries[i];
|
||||||
|
StringSetFindResult fr;
|
||||||
|
if (ns.hashes.count == 0) {
|
||||||
|
string_set_grow(&ns);
|
||||||
|
}
|
||||||
|
fr = string_set__find(&ns, e->key);
|
||||||
|
j = string_set__add_entry(&ns, e->key);
|
||||||
|
if (fr.entry_prev < 0) {
|
||||||
|
ns.hashes[fr.hash_index] = j;
|
||||||
|
} else {
|
||||||
|
ns.entries[fr.entry_prev].next = j;
|
||||||
|
}
|
||||||
|
ns.entries[j].next = fr.entry_index;
|
||||||
|
ns.entries[j].value = e->value;
|
||||||
|
if (string_set__full(&ns)) {
|
||||||
|
string_set_grow(&ns);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string_set_destroy(s);
|
||||||
|
*s = ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline bool string_set_exists(StringSet *s, String str) {
|
||||||
|
HashKey key = hash_string(str);
|
||||||
|
isize index = string_set__find(s, key).entry_index;
|
||||||
|
return index >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void string_set_add(StringSet *s, String str) {
|
||||||
|
isize index;
|
||||||
|
StringSetFindResult fr;
|
||||||
|
HashKey key = hash_string(str);
|
||||||
|
if (s->hashes.count == 0) {
|
||||||
|
string_set_grow(s);
|
||||||
|
}
|
||||||
|
fr = string_set__find(s, key);
|
||||||
|
if (fr.entry_index >= 0) {
|
||||||
|
index = fr.entry_index;
|
||||||
|
} else {
|
||||||
|
index = string_set__add_entry(s, key);
|
||||||
|
if (fr.entry_prev >= 0) {
|
||||||
|
s->entries[fr.entry_prev].next = index;
|
||||||
|
} else {
|
||||||
|
s->hashes[fr.hash_index] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->entries[index].value = str;
|
||||||
|
|
||||||
|
if (string_set__full(s)) {
|
||||||
|
string_set_grow(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void string_set__erase(StringSet *s, StringSetFindResult fr) {
|
||||||
|
StringSetFindResult last;
|
||||||
|
if (fr.entry_prev < 0) {
|
||||||
|
s->hashes[fr.hash_index] = s->entries[fr.entry_index].next;
|
||||||
|
} else {
|
||||||
|
s->entries[fr.entry_prev].next = s->entries[fr.entry_index].next;
|
||||||
|
}
|
||||||
|
if (fr.entry_index == s->entries.count-1) {
|
||||||
|
array_pop(&s->entries);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s->entries[fr.entry_index] = s->entries[s->entries.count-1];
|
||||||
|
last = string_set__find(s, s->entries[fr.entry_index].key);
|
||||||
|
if (last.entry_prev >= 0) {
|
||||||
|
s->entries[last.entry_prev].next = fr.entry_index;
|
||||||
|
} else {
|
||||||
|
s->hashes[last.hash_index] = fr.entry_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void string_set_remove(StringSet *s, String str) {
|
||||||
|
HashKey key = hash_string(str);
|
||||||
|
StringSetFindResult fr = string_set__find(s, key);
|
||||||
|
if (fr.entry_index >= 0) {
|
||||||
|
string_set__erase(s, fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_inline void string_set_clear(StringSet *s) {
|
||||||
|
array_clear(&s->hashes);
|
||||||
|
array_clear(&s->entries);
|
||||||
|
}
|
||||||
+25
-15
@@ -2436,7 +2436,31 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_Proc:
|
case Type_Proc:
|
||||||
str = gb_string_appendc(str, "proc(");
|
str = gb_string_appendc(str, "proc");
|
||||||
|
|
||||||
|
switch (type->Proc.calling_convention) {
|
||||||
|
case ProcCC_Odin:
|
||||||
|
break;
|
||||||
|
case ProcCC_Contextless:
|
||||||
|
str = gb_string_appendc(str, " \"contextless\" ");
|
||||||
|
break;
|
||||||
|
case ProcCC_CDecl:
|
||||||
|
str = gb_string_appendc(str, " \"cdecl\" ");
|
||||||
|
break;
|
||||||
|
case ProcCC_StdCall:
|
||||||
|
str = gb_string_appendc(str, " \"stdcall\" ");
|
||||||
|
break;
|
||||||
|
case ProcCC_FastCall:
|
||||||
|
str = gb_string_appendc(str, " \"fastcall\" ");
|
||||||
|
break;
|
||||||
|
// case ProcCC_VectorCall:
|
||||||
|
// str = gb_string_appendc(str, " \"vectorcall\" ");
|
||||||
|
// break;
|
||||||
|
// case ProcCC_ClrCall:
|
||||||
|
// str = gb_string_appendc(str, " \"clrcall\" ");
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
str = gb_string_appendc(str, "(");
|
||||||
if (type->Proc.params) {
|
if (type->Proc.params) {
|
||||||
str = write_type_to_string(str, type->Proc.params);
|
str = write_type_to_string(str, type->Proc.params);
|
||||||
}
|
}
|
||||||
@@ -2445,20 +2469,6 @@ gbString write_type_to_string(gbString str, Type *type) {
|
|||||||
str = gb_string_appendc(str, " -> ");
|
str = gb_string_appendc(str, " -> ");
|
||||||
str = write_type_to_string(str, type->Proc.results);
|
str = write_type_to_string(str, type->Proc.results);
|
||||||
}
|
}
|
||||||
switch (type->Proc.calling_convention) {
|
|
||||||
case ProcCC_Odin:
|
|
||||||
// str = gb_string_appendc(str, " #cc_odin");
|
|
||||||
break;
|
|
||||||
case ProcCC_C:
|
|
||||||
str = gb_string_appendc(str, " #cc_c");
|
|
||||||
break;
|
|
||||||
case ProcCC_Std:
|
|
||||||
str = gb_string_appendc(str, " #cc_std");
|
|
||||||
break;
|
|
||||||
case ProcCC_Fast:
|
|
||||||
str = gb_string_appendc(str, " #cc_fast");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type_BitField:
|
case Type_BitField:
|
||||||
|
|||||||
Reference in New Issue
Block a user