mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Very Basic Profiling
This commit is contained in:
+11
-17
@@ -551,6 +551,8 @@ void destroy_checker_info(CheckerInfo *i) {
|
|||||||
|
|
||||||
|
|
||||||
void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) {
|
void init_checker(Checker *c, Parser *parser, BaseTypeSizes sizes) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
gbAllocator a = gb_heap_allocator();
|
gbAllocator a = gb_heap_allocator();
|
||||||
|
|
||||||
c->parser = parser;
|
c->parser = parser;
|
||||||
@@ -890,6 +892,8 @@ Map<Entity *> generate_minimum_dependency_map(CheckerInfo *info, Entity *start)
|
|||||||
#include "stmt.cpp"
|
#include "stmt.cpp"
|
||||||
|
|
||||||
void init_preload_types(Checker *c) {
|
void init_preload_types(Checker *c) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (t_type_info == NULL) {
|
if (t_type_info == NULL) {
|
||||||
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
Entity *e = current_scope_lookup_entity(c->global_scope, make_string("Type_Info"));
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
@@ -947,7 +951,6 @@ void init_preload_types(Checker *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_parsed_files(Checker *c) {
|
void check_parsed_files(Checker *c) {
|
||||||
|
|
||||||
Array<AstNode *> import_decls;
|
Array<AstNode *> import_decls;
|
||||||
array_init(&import_decls, gb_heap_allocator());
|
array_init(&import_decls, gb_heap_allocator());
|
||||||
defer (array_free(&import_decls));
|
defer (array_free(&import_decls));
|
||||||
@@ -983,6 +986,8 @@ void check_parsed_files(Checker *c) {
|
|||||||
|
|
||||||
// Collect Entities
|
// Collect Entities
|
||||||
for_array(i, c->parser->files) {
|
for_array(i, c->parser->files) {
|
||||||
|
PROF_SCOPED("Collect Entities");
|
||||||
|
|
||||||
AstFile *f = &c->parser->files[i];
|
AstFile *f = &c->parser->files[i];
|
||||||
add_curr_ast_file(c, f);
|
add_curr_ast_file(c, f);
|
||||||
|
|
||||||
@@ -1090,6 +1095,8 @@ void check_parsed_files(Checker *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for_array(i, c->parser->files) {
|
for_array(i, c->parser->files) {
|
||||||
|
PROF_SCOPED("Import Entities");
|
||||||
|
|
||||||
AstFile *f = &c->parser->files[i];
|
AstFile *f = &c->parser->files[i];
|
||||||
add_curr_ast_file(c, f);
|
add_curr_ast_file(c, f);
|
||||||
|
|
||||||
@@ -1186,6 +1193,7 @@ void check_parsed_files(Checker *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto check_global_entity = [](Checker *c, EntityKind kind) {
|
auto check_global_entity = [](Checker *c, EntityKind kind) {
|
||||||
|
PROF_SCOPED("check_global_entity");
|
||||||
for_array(i, c->info.entities.entries) {
|
for_array(i, c->info.entities.entries) {
|
||||||
auto *entry = &c->info.entities.entries[i];
|
auto *entry = &c->info.entities.entries[i];
|
||||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||||
@@ -1242,24 +1250,10 @@ void check_parsed_files(Checker *c) {
|
|||||||
check_proc_body(c, pi->token, pi->decl, pi->type, pi->body);
|
check_proc_body(c, pi->token, pi->decl, pi->type, pi->body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false) {
|
|
||||||
gb_printf("Dependency graph:\n");
|
|
||||||
for_array(i, c->info.entities.entries) {
|
|
||||||
auto *entry = &c->info.entities.entries[i];
|
|
||||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
|
||||||
DeclInfo *d = entry->value;
|
|
||||||
if (d->deps.entries.count > 0) {
|
|
||||||
gb_printf("\t%.*s depends on\n", LIT(e->token.string));
|
|
||||||
for_array(j, d->deps.entries) {
|
|
||||||
Entity *e = cast(Entity *)cast(uintptr)d->deps.entries[j].key.key;
|
|
||||||
gb_printf("\t\t%.*s\n", LIT(e->token.string));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add untyped expression values
|
// Add untyped expression values
|
||||||
for_array(i, c->info.untyped.entries) {
|
for_array(i, c->info.untyped.entries) {
|
||||||
|
PROF_SCOPED("Untyped expr values");
|
||||||
|
|
||||||
auto *entry = &c->info.untyped.entries[i];
|
auto *entry = &c->info.untyped.entries[i];
|
||||||
HashKey key = entry->key;
|
HashKey key = entry->key;
|
||||||
AstNode *expr = cast(AstNode *)cast(uintptr)key.key;
|
AstNode *expr = cast(AstNode *)cast(uintptr)key.key;
|
||||||
|
|||||||
+63
-2
@@ -47,6 +47,8 @@ b32 check_is_assignable_to_using_subtype(Type *dst, Type *src) {
|
|||||||
|
|
||||||
|
|
||||||
b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argument = false) {
|
b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argument = false) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (operand->mode == Addressing_Invalid ||
|
if (operand->mode == Addressing_Invalid ||
|
||||||
type == t_invalid) {
|
type == t_invalid) {
|
||||||
return true;
|
return true;
|
||||||
@@ -151,6 +153,8 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
|
|||||||
|
|
||||||
// NOTE(bill): `content_name` is for debugging and error messages
|
// NOTE(bill): `content_name` is for debugging and error messages
|
||||||
void check_assignment(Checker *c, Operand *operand, Type *type, String context_name, b32 is_argument = false) {
|
void check_assignment(Checker *c, Operand *operand, Type *type, String context_name, b32 is_argument = false) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
check_not_tuple(c, operand);
|
check_not_tuple(c, operand);
|
||||||
if (operand->mode == Addressing_Invalid)
|
if (operand->mode == Addressing_Invalid)
|
||||||
return;
|
return;
|
||||||
@@ -206,6 +210,8 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
|
|||||||
|
|
||||||
|
|
||||||
void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map<Entity *> *entity_map) {
|
void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map<Entity *> *entity_map) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
t = base_type(type_deref(t));
|
t = base_type(type_deref(t));
|
||||||
gbString str = expr_to_string(node);
|
gbString str = expr_to_string(node);
|
||||||
defer (gb_string_free(str));
|
defer (gb_string_free(str));
|
||||||
@@ -239,6 +245,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
Entity **fields, isize field_count,
|
Entity **fields, isize field_count,
|
||||||
Entity **other_fields, isize other_field_count,
|
Entity **other_fields, isize other_field_count,
|
||||||
CycleChecker *cycle_checker, String context) {
|
CycleChecker *cycle_checker, String context) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
Map<Entity *> entity_map = {};
|
Map<Entity *> entity_map = {};
|
||||||
map_init(&entity_map, gb_heap_allocator());
|
map_init(&entity_map, gb_heap_allocator());
|
||||||
@@ -487,6 +494,8 @@ GB_COMPARE_PROC(cmp_struct_entity_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecker *cycle_checker) {
|
void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecker *cycle_checker) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(is_type_struct(struct_type));
|
GB_ASSERT(is_type_struct(struct_type));
|
||||||
ast_node(st, StructType, node);
|
ast_node(st, StructType, node);
|
||||||
|
|
||||||
@@ -549,6 +558,8 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecke
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) {
|
void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(is_type_union(union_type));
|
GB_ASSERT(is_type_union(union_type));
|
||||||
ast_node(ut, UnionType, node);
|
ast_node(ut, UnionType, node);
|
||||||
|
|
||||||
@@ -583,6 +594,8 @@ void check_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) {
|
void check_raw_union_type(Checker *c, Type *union_type, AstNode *node, CycleChecker *cycle_checker) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(node->kind == AstNode_RawUnionType);
|
GB_ASSERT(node->kind == AstNode_RawUnionType);
|
||||||
GB_ASSERT(is_type_raw_union(union_type));
|
GB_ASSERT(is_type_raw_union(union_type));
|
||||||
ast_node(ut, RawUnionType, node);
|
ast_node(ut, RawUnionType, node);
|
||||||
@@ -639,6 +652,8 @@ GB_COMPARE_PROC(cmp_enum_order) {
|
|||||||
|
|
||||||
|
|
||||||
void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) {
|
void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(node->kind == AstNode_EnumType);
|
GB_ASSERT(node->kind == AstNode_EnumType);
|
||||||
GB_ASSERT(is_type_enum(enum_type));
|
GB_ASSERT(is_type_enum(enum_type));
|
||||||
ast_node(et, EnumType, node);
|
ast_node(et, EnumType, node);
|
||||||
@@ -749,6 +764,8 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_variadic_) {
|
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_variadic_) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (params.count == 0) {
|
if (params.count == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -809,6 +826,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, b32 *is_va
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type *check_get_results(Checker *c, Scope *scope, AstNodeArray results) {
|
Type *check_get_results(Checker *c, Scope *scope, AstNodeArray results) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (results.count == 0) {
|
if (results.count == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -834,6 +853,8 @@ Type *check_get_results(Checker *c, Scope *scope, AstNodeArray results) {
|
|||||||
|
|
||||||
|
|
||||||
void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
ast_node(pt, ProcType, proc_type_node);
|
ast_node(pt, ProcType, proc_type_node);
|
||||||
|
|
||||||
b32 variadic = false;
|
b32 variadic = false;
|
||||||
@@ -857,6 +878,8 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node) {
|
|||||||
|
|
||||||
|
|
||||||
void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, CycleChecker *cycle_checker) {
|
void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, CycleChecker *cycle_checker) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(n->kind == AstNode_Ident);
|
GB_ASSERT(n->kind == AstNode_Ident);
|
||||||
o->mode = Addressing_Invalid;
|
o->mode = Addressing_Invalid;
|
||||||
o->expr = n;
|
o->expr = n;
|
||||||
@@ -959,6 +982,8 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
|||||||
}
|
}
|
||||||
|
|
||||||
i64 check_array_count(Checker *c, AstNode *e) {
|
i64 check_array_count(Checker *c, AstNode *e) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (e == NULL) {
|
if (e == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -986,6 +1011,8 @@ i64 check_array_count(Checker *c, AstNode *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_checker) {
|
Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_checker) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
ExactValue null_value = {ExactValue_Invalid};
|
ExactValue null_value = {ExactValue_Invalid};
|
||||||
Type *type = NULL;
|
Type *type = NULL;
|
||||||
gbString err_str = NULL;
|
gbString err_str = NULL;
|
||||||
@@ -1258,6 +1285,8 @@ b32 check_binary_op(Checker *c, Operand *o, Token op) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value) {
|
b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, ExactValue *out_value) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (in_value.kind == ExactValue_Invalid) {
|
if (in_value.kind == ExactValue_Invalid) {
|
||||||
// NOTE(bill): There's already been an error
|
// NOTE(bill): There's already been an error
|
||||||
return true;
|
return true;
|
||||||
@@ -1334,6 +1363,8 @@ b32 check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exac
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_is_expressible(Checker *c, Operand *o, Type *type) {
|
void check_is_expressible(Checker *c, Operand *o, Type *type) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(type->kind == Type_Basic);
|
GB_ASSERT(type->kind == Type_Basic);
|
||||||
GB_ASSERT(o->mode == Addressing_Constant);
|
GB_ASSERT(o->mode == Addressing_Constant);
|
||||||
if (!check_value_is_expressible(c, o->value, type, &o->value)) {
|
if (!check_value_is_expressible(c, o->value, type, &o->value)) {
|
||||||
@@ -1369,6 +1400,8 @@ b32 check_is_expr_vector_index(Checker *c, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
switch (op.kind) {
|
switch (op.kind) {
|
||||||
case Token_Pointer: { // Pointer address
|
case Token_Pointer: { // Pointer address
|
||||||
if (o->mode != Addressing_Variable ||
|
if (o->mode != Addressing_Variable ||
|
||||||
@@ -1442,6 +1475,8 @@ void check_unary_expr(Checker *c, Operand *o, Token op, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
|
||||||
defer (gb_temp_arena_memory_end(tmp));
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
@@ -1506,10 +1541,11 @@ void check_comparison(Checker *c, Operand *x, Operand *y, Token op) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
||||||
ast_node(be, BinaryExpr, node);
|
ast_node(be, BinaryExpr, node);
|
||||||
|
|
||||||
|
|
||||||
ExactValue x_val = {};
|
ExactValue x_val = {};
|
||||||
if (x->mode == Addressing_Constant) {
|
if (x->mode == Addressing_Constant) {
|
||||||
x_val = exact_value_to_integer(x->value);
|
x_val = exact_value_to_integer(x->value);
|
||||||
@@ -1600,8 +1636,11 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b32 check_is_castable_to(Checker *c, Operand *operand, Type *y) {
|
b32 check_is_castable_to(Checker *c, Operand *operand, Type *y) {
|
||||||
if (check_is_assignable_to(c, operand, y))
|
PROF_PROC();
|
||||||
|
|
||||||
|
if (check_is_assignable_to(c, operand, y)) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
Type *x = operand->type;
|
Type *x = operand->type;
|
||||||
Type *xb = base_type(x);
|
Type *xb = base_type(x);
|
||||||
@@ -1690,6 +1729,8 @@ String check_down_cast_name(Type *dst_, Type *src_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
GB_ASSERT(node->kind == AstNode_BinaryExpr);
|
||||||
Operand y_ = {}, *y = &y_;
|
Operand y_ = {}, *y = &y_;
|
||||||
gbString err_str = NULL;
|
gbString err_str = NULL;
|
||||||
@@ -1956,6 +1997,8 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
|||||||
|
|
||||||
|
|
||||||
void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) {
|
void update_expr_type(Checker *c, AstNode *e, Type *type, b32 final) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
HashKey key = hash_pointer(e);
|
HashKey key = hash_pointer(e);
|
||||||
ExpressionInfo *found = map_get(&c->info.untyped, key);
|
ExpressionInfo *found = map_get(&c->info.untyped, key);
|
||||||
if (found == NULL)
|
if (found == NULL)
|
||||||
@@ -2029,6 +2072,8 @@ void convert_untyped_error(Checker *c, Operand *operand, Type *target_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level) {
|
void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT_NOT_NULL(target_type);
|
GB_ASSERT_NOT_NULL(target_type);
|
||||||
if (operand->mode == Addressing_Invalid ||
|
if (operand->mode == Addressing_Invalid ||
|
||||||
is_type_typed(operand->type) ||
|
is_type_typed(operand->type) ||
|
||||||
@@ -2109,6 +2154,8 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
|
|||||||
}
|
}
|
||||||
|
|
||||||
b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
|
b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *value) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
check_expr(c, &operand, index_value);
|
check_expr(c, &operand, index_value);
|
||||||
if (operand.mode == Addressing_Invalid) {
|
if (operand.mode == Addressing_Invalid) {
|
||||||
@@ -2163,6 +2210,8 @@ b32 check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
Entity *check_selector(Checker *c, Operand *operand, AstNode *node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
ast_node(se, SelectorExpr, node);
|
ast_node(se, SelectorExpr, node);
|
||||||
|
|
||||||
b32 check_op_expr = true;
|
b32 check_op_expr = true;
|
||||||
@@ -2266,6 +2315,8 @@ error:
|
|||||||
}
|
}
|
||||||
|
|
||||||
b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) {
|
b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(call->kind == AstNode_CallExpr);
|
GB_ASSERT(call->kind == AstNode_CallExpr);
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
BuiltinProc *bp = &builtin_procs[id];
|
BuiltinProc *bp = &builtin_procs[id];
|
||||||
@@ -3064,6 +3115,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
|
|
||||||
|
|
||||||
void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
|
void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode *call) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(call->kind == AstNode_CallExpr);
|
GB_ASSERT(call->kind == AstNode_CallExpr);
|
||||||
GB_ASSERT(proc_type->kind == Type_Proc);
|
GB_ASSERT(proc_type->kind == Type_Proc);
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
@@ -3188,6 +3241,8 @@ Entity *find_using_index_expr(Type *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
ExprKind check_call_expr(Checker *c, Operand *operand, AstNode *call) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(call->kind == AstNode_CallExpr);
|
GB_ASSERT(call->kind == AstNode_CallExpr);
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
check_expr_or_type(c, operand, ce->proc);
|
check_expr_or_type(c, operand, ce->proc);
|
||||||
@@ -3318,6 +3373,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(cl, CompoundLit, node);
|
case_ast_node(cl, CompoundLit, node);
|
||||||
|
PROF_SCOPED("check__expr_base - CompoundLit");
|
||||||
|
|
||||||
Type *type = type_hint;
|
Type *type = type_hint;
|
||||||
b32 ellipsis_array = false;
|
b32 ellipsis_array = false;
|
||||||
b32 is_constant = true;
|
b32 is_constant = true;
|
||||||
@@ -3557,6 +3614,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
|
|
||||||
|
|
||||||
case_ast_node(ie, IndexExpr, node);
|
case_ast_node(ie, IndexExpr, node);
|
||||||
|
PROF_SCOPED("check__expr_base - IndexExpr");
|
||||||
|
|
||||||
check_expr(c, o, ie->expr);
|
check_expr(c, o, ie->expr);
|
||||||
if (o->mode == Addressing_Invalid) {
|
if (o->mode == Addressing_Invalid) {
|
||||||
goto error;
|
goto error;
|
||||||
@@ -3638,6 +3697,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
|
|
||||||
|
|
||||||
case_ast_node(se, SliceExpr, node);
|
case_ast_node(se, SliceExpr, node);
|
||||||
|
PROF_SCOPED("check__expr_base - SliceExpr");
|
||||||
|
|
||||||
check_expr(c, o, se->expr);
|
check_expr(c, o, se->expr);
|
||||||
if (o->mode == Addressing_Invalid)
|
if (o->mode == Addressing_Invalid)
|
||||||
goto error;
|
goto error;
|
||||||
|
|||||||
+54
-6
@@ -123,6 +123,8 @@ b32 check_has_break_list(AstNodeArray stmts, b32 implicit) {
|
|||||||
|
|
||||||
|
|
||||||
b32 check_has_break(AstNode *stmt, b32 implicit) {
|
b32 check_has_break(AstNode *stmt, b32 implicit) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
switch (stmt->kind) {
|
switch (stmt->kind) {
|
||||||
case AstNode_BranchStmt:
|
case AstNode_BranchStmt:
|
||||||
if (stmt->BranchStmt.token.kind == Token_break) {
|
if (stmt->BranchStmt.token.kind == Token_break) {
|
||||||
@@ -152,6 +154,8 @@ b32 check_has_break(AstNode *stmt, b32 implicit) {
|
|||||||
// TODO(bill): This is a mild hack and should be probably handled properly
|
// TODO(bill): This is a mild hack and should be probably handled properly
|
||||||
// TODO(bill): Warn/err against code after `return` that it won't be executed
|
// TODO(bill): Warn/err against code after `return` that it won't be executed
|
||||||
b32 check_is_terminating(AstNode *node) {
|
b32 check_is_terminating(AstNode *node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
switch (node->kind) {
|
switch (node->kind) {
|
||||||
case_ast_node(rs, ReturnStmt, node);
|
case_ast_node(rs, ReturnStmt, node);
|
||||||
return true;
|
return true;
|
||||||
@@ -224,6 +228,8 @@ b32 check_is_terminating(AstNode *node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (op_a->mode == Addressing_Invalid ||
|
if (op_a->mode == Addressing_Invalid ||
|
||||||
op_a->type == t_invalid) {
|
op_a->type == t_invalid) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -289,6 +295,8 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
|||||||
|
|
||||||
// NOTE(bill): `content_name` is for debugging
|
// NOTE(bill): `content_name` is for debugging
|
||||||
Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String context_name) {
|
Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String context_name) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (operand->mode == Addressing_Invalid ||
|
if (operand->mode == Addressing_Invalid ||
|
||||||
operand->type == t_invalid ||
|
operand->type == t_invalid ||
|
||||||
e->type == t_invalid) {
|
e->type == t_invalid) {
|
||||||
@@ -336,6 +344,8 @@ Type *check_init_variable(Checker *c, Entity *e, Operand *operand, String contex
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) {
|
void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArray inits, String context_name) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if ((lhs == NULL || lhs_count == 0) && inits.count == 0) {
|
if ((lhs == NULL || lhs_count == 0) && inits.count == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -382,6 +392,8 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (operand->mode == Addressing_Invalid ||
|
if (operand->mode == Addressing_Invalid ||
|
||||||
operand->type == t_invalid ||
|
operand->type == t_invalid ||
|
||||||
e->type == t_invalid) {
|
e->type == t_invalid) {
|
||||||
@@ -425,6 +437,8 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
|
|||||||
|
|
||||||
|
|
||||||
void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr) {
|
void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_expr) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(e->type == NULL);
|
GB_ASSERT(e->type == NULL);
|
||||||
|
|
||||||
if (e->Variable.visited) {
|
if (e->Variable.visited) {
|
||||||
@@ -454,6 +468,8 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, CycleChecker *cycle_checker) {
|
void check_type_decl(Checker *c, Entity *e, AstNode *type_expr, Type *def, CycleChecker *cycle_checker) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(e->type == NULL);
|
GB_ASSERT(e->type == NULL);
|
||||||
Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
|
Type *named = make_type_named(c->allocator, e->token.string, NULL, e);
|
||||||
named->Named.type_name = e;
|
named->Named.type_name = e;
|
||||||
@@ -517,12 +533,14 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod
|
|||||||
}
|
}
|
||||||
|
|
||||||
push_procedure(c, type);
|
push_procedure(c, type);
|
||||||
ast_node(bs, BlockStmt, body);
|
{
|
||||||
// TODO(bill): Check declarations first (except mutable variable declarations)
|
ast_node(bs, BlockStmt, body);
|
||||||
check_stmt_list(c, bs->stmts, 0);
|
// TODO(bill): Check declarations first (except mutable variable declarations)
|
||||||
if (type->Proc.result_count > 0) {
|
check_stmt_list(c, bs->stmts, 0);
|
||||||
if (!check_is_terminating(body)) {
|
if (type->Proc.result_count > 0) {
|
||||||
error(bs->close, "Missing return statement at the end of the procedure");
|
if (!check_is_terminating(body)) {
|
||||||
|
error(bs->close, "Missing return statement at the end of the procedure");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pop_procedure(c);
|
pop_procedure(c);
|
||||||
@@ -570,6 +588,8 @@ b32 are_signatures_similar_enough(Type *a_, Type *b_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(e->type == NULL);
|
GB_ASSERT(e->type == NULL);
|
||||||
|
|
||||||
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
|
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
|
||||||
@@ -665,6 +685,8 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr) {
|
void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count, AstNode *type_expr, AstNode *init_expr) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
GB_ASSERT(e->type == NULL);
|
GB_ASSERT(e->type == NULL);
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
|
||||||
@@ -704,6 +726,8 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count
|
|||||||
|
|
||||||
|
|
||||||
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, CycleChecker *cycle_checker) {
|
void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, CycleChecker *cycle_checker) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
if (e->type != NULL) {
|
if (e->type != NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -745,6 +769,8 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
|
|||||||
|
|
||||||
|
|
||||||
void check_var_decl_node(Checker *c, AstNode *node) {
|
void check_var_decl_node(Checker *c, AstNode *node) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
ast_node(vd, VarDecl, node);
|
ast_node(vd, VarDecl, node);
|
||||||
isize entity_count = vd->names.count;
|
isize entity_count = vd->names.count;
|
||||||
isize entity_index = 0;
|
isize entity_index = 0;
|
||||||
@@ -839,6 +865,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_ast_node(_, BadDecl, node); case_end;
|
case_ast_node(_, BadDecl, node); case_end;
|
||||||
|
|
||||||
case_ast_node(es, ExprStmt, node)
|
case_ast_node(es, ExprStmt, node)
|
||||||
|
PROF_SCOPED("check_stmt - ExprStmt");
|
||||||
|
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
ExprKind kind = check_expr_base(c, &operand, es->expr);
|
ExprKind kind = check_expr_base(c, &operand, es->expr);
|
||||||
switch (operand.mode) {
|
switch (operand.mode) {
|
||||||
@@ -869,6 +897,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ids, IncDecStmt, node);
|
case_ast_node(ids, IncDecStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - IncDecStmt");
|
||||||
|
|
||||||
Token op = ids->op;
|
Token op = ids->op;
|
||||||
switch (ids->op.kind) {
|
switch (ids->op.kind) {
|
||||||
case Token_Increment:
|
case Token_Increment:
|
||||||
@@ -908,6 +938,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(as, AssignStmt, node);
|
case_ast_node(as, AssignStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - AssignStmt");
|
||||||
|
|
||||||
switch (as->op.kind) {
|
switch (as->op.kind) {
|
||||||
case Token_Eq: {
|
case Token_Eq: {
|
||||||
// a, b, c = 1, 2, 3; // Multisided
|
// a, b, c = 1, 2, 3; // Multisided
|
||||||
@@ -988,6 +1020,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(is, IfStmt, node);
|
case_ast_node(is, IfStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - IfStmt");
|
||||||
|
|
||||||
check_open_scope(c, node);
|
check_open_scope(c, node);
|
||||||
defer (check_close_scope(c));
|
defer (check_close_scope(c));
|
||||||
|
|
||||||
@@ -1019,6 +1053,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(rs, ReturnStmt, node);
|
case_ast_node(rs, ReturnStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - ReturnStmt");
|
||||||
|
|
||||||
GB_ASSERT(c->proc_stack.count > 0);
|
GB_ASSERT(c->proc_stack.count > 0);
|
||||||
|
|
||||||
if (c->in_defer) {
|
if (c->in_defer) {
|
||||||
@@ -1052,6 +1088,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(fs, ForStmt, node);
|
case_ast_node(fs, ForStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - ForStmt");
|
||||||
|
|
||||||
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
||||||
check_open_scope(c, node);
|
check_open_scope(c, node);
|
||||||
defer (check_close_scope(c));
|
defer (check_close_scope(c));
|
||||||
@@ -1073,6 +1111,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ms, MatchStmt, node);
|
case_ast_node(ms, MatchStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - MatchStmt");
|
||||||
|
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
|
|
||||||
mod_flags |= Stmt_BreakAllowed;
|
mod_flags |= Stmt_BreakAllowed;
|
||||||
@@ -1215,6 +1255,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ms, TypeMatchStmt, node);
|
case_ast_node(ms, TypeMatchStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - TypeMatchStmt");
|
||||||
|
|
||||||
Operand x = {};
|
Operand x = {};
|
||||||
|
|
||||||
mod_flags |= Stmt_BreakAllowed;
|
mod_flags |= Stmt_BreakAllowed;
|
||||||
@@ -1366,6 +1408,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(us, UsingStmt, node);
|
case_ast_node(us, UsingStmt, node);
|
||||||
|
PROF_SCOPED("check_stmt - UsingStmt");
|
||||||
|
|
||||||
switch (us->node->kind) {
|
switch (us->node->kind) {
|
||||||
case_ast_node(es, ExprStmt, us->node);
|
case_ast_node(es, ExprStmt, us->node);
|
||||||
// TODO(bill): Allow for just a LHS expression list rather than this silly code
|
// TODO(bill): Allow for just a LHS expression list rather than this silly code
|
||||||
@@ -1485,6 +1529,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(vd, VarDecl, us->node);
|
case_ast_node(vd, VarDecl, us->node);
|
||||||
|
PROF_SCOPED("check_stmt - VarDecl");
|
||||||
|
|
||||||
if (vd->names.count > 1 && vd->type != NULL) {
|
if (vd->names.count > 1 && vd->type != NULL) {
|
||||||
error(us->token, "`using` can only be applied to one variable of the same type");
|
error(us->token, "`using` can only be applied to one variable of the same type");
|
||||||
}
|
}
|
||||||
@@ -1559,6 +1605,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(pd, ProcDecl, node);
|
case_ast_node(pd, ProcDecl, node);
|
||||||
|
PROF_SCOPED("check_stmt - ProcDecl");
|
||||||
|
|
||||||
// NOTE(bill): This must be handled here so it has access to the parent scope stuff
|
// NOTE(bill): This must be handled here so it has access to the parent scope stuff
|
||||||
// e.g. using
|
// e.g. using
|
||||||
Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL);
|
Entity *e = make_entity_procedure(c->allocator, c->context.scope, pd->name->Ident, NULL);
|
||||||
|
|||||||
@@ -918,7 +918,9 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
|||||||
String str = f->token.string;
|
String str = f->token.string;
|
||||||
|
|
||||||
if (field_name == str) {
|
if (field_name == str) {
|
||||||
Selection sel = {f, {}, i};
|
Selection sel = {};
|
||||||
|
sel.entity = f;
|
||||||
|
selection_add_index(&sel, i);
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -930,7 +932,9 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ
|
|||||||
String str = f->token.string;
|
String str = f->token.string;
|
||||||
|
|
||||||
if (field_name == str) {
|
if (field_name == str) {
|
||||||
Selection sel = {f, {}, i};
|
Selection sel = {};
|
||||||
|
sel.entity = f;
|
||||||
|
selection_add_index(&sel, i);
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1421,6 +1421,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
|
|||||||
ssa_emit_jump(proc, proc->entry_block);
|
ssa_emit_jump(proc, proc->entry_block);
|
||||||
|
|
||||||
ssa_optimize_blocks(proc);
|
ssa_optimize_blocks(proc);
|
||||||
|
#if 0
|
||||||
ssa_build_referrers(proc);
|
ssa_build_referrers(proc);
|
||||||
ssa_build_dom_tree(proc);
|
ssa_build_dom_tree(proc);
|
||||||
|
|
||||||
@@ -1430,7 +1431,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
|
|||||||
// [ ] Local stored once? Replace loads with dominating store
|
// [ ] Local stored once? Replace loads with dominating store
|
||||||
// [ ] Convert to phi nodes
|
// [ ] Convert to phi nodes
|
||||||
ssa_opt_mem2reg(proc);
|
ssa_opt_mem2reg(proc);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Number registers
|
// Number registers
|
||||||
i32 reg_index = 0;
|
i32 reg_index = 0;
|
||||||
|
|||||||
+15
-37
@@ -1,6 +1,5 @@
|
|||||||
// #define DISPLAY_TIMING
|
|
||||||
|
|
||||||
#include "common.cpp"
|
#include "common.cpp"
|
||||||
|
#include "profiler.cpp"
|
||||||
#include "unicode.cpp"
|
#include "unicode.cpp"
|
||||||
#include "tokenizer.cpp"
|
#include "tokenizer.cpp"
|
||||||
#include "parser.cpp"
|
#include "parser.cpp"
|
||||||
@@ -8,7 +7,9 @@
|
|||||||
#include "checker/checker.cpp"
|
#include "checker/checker.cpp"
|
||||||
#include "codegen/codegen.cpp"
|
#include "codegen/codegen.cpp"
|
||||||
|
|
||||||
i32 win32_exec_command_line_app(char *fmt, ...) {
|
i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
|
||||||
|
// PROF_SCOPED_STR(name);
|
||||||
|
|
||||||
STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)};
|
STARTUPINFOW start_info = {gb_size_of(STARTUPINFOW)};
|
||||||
PROCESS_INFORMATION pi = {};
|
PROCESS_INFORMATION pi = {};
|
||||||
char cmd_line[2048] = {};
|
char cmd_line[2048] = {};
|
||||||
@@ -51,25 +52,6 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DISPLAY_TIMING)
|
|
||||||
#define INIT_TIMER() f64 start_time = gb_time_now(), end_time = 0, total_time = 0
|
|
||||||
#define PRINT_TIMER(section) do { \
|
|
||||||
f64 diff; \
|
|
||||||
end_time = gb_time_now(); \
|
|
||||||
diff = end_time - start_time; \
|
|
||||||
total_time += diff; \
|
|
||||||
gb_printf_err("%s: %.1f ms\n", section, diff*1000.0); \
|
|
||||||
start_time = gb_time_now(); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define PRINT_ACCUMULATION() do { \
|
|
||||||
gb_printf_err("Total compilation time: %.1f ms\n", total_time*1000.0); \
|
|
||||||
} while (0)
|
|
||||||
#else
|
|
||||||
#define INIT_TIMER()
|
|
||||||
#define PRINT_TIMER(section)
|
|
||||||
#define PRINT_ACCUMULATION()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
enum ArchKind {
|
enum ArchKind {
|
||||||
@@ -113,14 +95,14 @@ int main(int argc, char **argv) {
|
|||||||
gb_printf_err("using: %s [run] <filename> \n", argv[0]);
|
gb_printf_err("using: %s [run] <filename> \n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
prof_init();
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
init_string_buffer_memory();
|
init_string_buffer_memory();
|
||||||
init_global_error_collector();
|
init_global_error_collector();
|
||||||
|
|
||||||
String module_dir = get_module_dir();
|
|
||||||
|
|
||||||
INIT_TIMER();
|
String module_dir = get_module_dir();
|
||||||
|
|
||||||
init_universal_scope();
|
init_universal_scope();
|
||||||
|
|
||||||
@@ -142,7 +124,6 @@ int main(int argc, char **argv) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT_TIMER("Syntax Parser");
|
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
Checker checker = {};
|
Checker checker = {};
|
||||||
@@ -154,7 +135,6 @@ int main(int argc, char **argv) {
|
|||||||
check_parsed_files(&checker);
|
check_parsed_files(&checker);
|
||||||
|
|
||||||
|
|
||||||
PRINT_TIMER("Semantic Checker");
|
|
||||||
#endif
|
#endif
|
||||||
#if 1
|
#if 1
|
||||||
ssaGen ssa = {};
|
ssaGen ssa = {};
|
||||||
@@ -165,11 +145,11 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
ssa_gen_tree(&ssa);
|
ssa_gen_tree(&ssa);
|
||||||
|
|
||||||
PRINT_TIMER("SSA Tree");
|
|
||||||
// TODO(bill): Speedup writing to file for IR code
|
// TODO(bill): Speedup writing to file for IR code
|
||||||
ssa_gen_ir(&ssa);
|
ssa_gen_ir(&ssa);
|
||||||
|
|
||||||
PRINT_TIMER("SSA IR");
|
prof_print_all();
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
|
||||||
char const *output_name = ssa.output_file.filename;
|
char const *output_name = ssa.output_file.filename;
|
||||||
@@ -181,7 +161,7 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
i32 exit_code = 0;
|
i32 exit_code = 0;
|
||||||
// For more passes arguments: http://llvm.org/docs/Passes.html
|
// For more passes arguments: http://llvm.org/docs/Passes.html
|
||||||
exit_code = win32_exec_command_line_app(
|
exit_code = win32_exec_command_line_app("llvm-opt",
|
||||||
"%.*sbin/opt %s -o %.*s.bc "
|
"%.*sbin/opt %s -o %.*s.bc "
|
||||||
"-mem2reg "
|
"-mem2reg "
|
||||||
"-memcpyopt "
|
"-memcpyopt "
|
||||||
@@ -196,10 +176,9 @@ int main(int argc, char **argv) {
|
|||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT_TIMER("llvm-opt");
|
|
||||||
|
|
||||||
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
|
// For more arguments: http://llvm.org/docs/CommandGuide/llc.html
|
||||||
exit_code = win32_exec_command_line_app(
|
exit_code = win32_exec_command_line_app("llvm-llc",
|
||||||
"%.*sbin/llc %.*s.bc -filetype=obj -O%d "
|
"%.*sbin/llc %.*s.bc -filetype=obj -O%d "
|
||||||
"%.*s "
|
"%.*s "
|
||||||
// "-debug-pass=Arguments "
|
// "-debug-pass=Arguments "
|
||||||
@@ -212,7 +191,6 @@ int main(int argc, char **argv) {
|
|||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRINT_TIMER("llvm-llc");
|
|
||||||
|
|
||||||
gbString lib_str = gb_string_make(gb_heap_allocator(), "Kernel32.lib");
|
gbString lib_str = gb_string_make(gb_heap_allocator(), "Kernel32.lib");
|
||||||
// defer (gb_string_free(lib_str));
|
// defer (gb_string_free(lib_str));
|
||||||
@@ -223,7 +201,7 @@ int main(int argc, char **argv) {
|
|||||||
" %.*s.lib", LIT(lib));
|
" %.*s.lib", LIT(lib));
|
||||||
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
lib_str = gb_string_appendc(lib_str, lib_str_buf);
|
||||||
}
|
}
|
||||||
exit_code = win32_exec_command_line_app(
|
exit_code = win32_exec_command_line_app("msvc-link",
|
||||||
"link %.*s.obj -OUT:%.*s.exe %s "
|
"link %.*s.obj -OUT:%.*s.exe %s "
|
||||||
"/defaultlib:libcmt "
|
"/defaultlib:libcmt "
|
||||||
"/nologo /incremental:no /opt:ref /subsystem:console "
|
"/nologo /incremental:no /opt:ref /subsystem:console "
|
||||||
@@ -234,15 +212,15 @@ int main(int argc, char **argv) {
|
|||||||
if (exit_code != 0) {
|
if (exit_code != 0) {
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
// prof_print_all();
|
||||||
PRINT_TIMER("msvc-link");
|
|
||||||
PRINT_ACCUMULATION();
|
|
||||||
|
|
||||||
if (run_output) {
|
if (run_output) {
|
||||||
win32_exec_command_line_app("%.*s.exe", cast(int)base_name_len, output_name);
|
win32_exec_command_line_app("odin run", "%.*s.exe", cast(int)base_name_len, output_name);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-8
@@ -2848,15 +2848,18 @@ ParseFileError init_ast_file(AstFile *f, String fullpath) {
|
|||||||
TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
|
TokenizerInitError err = init_tokenizer(&f->tokenizer, fullpath);
|
||||||
if (err == TokenizerInit_None) {
|
if (err == TokenizerInit_None) {
|
||||||
array_init(&f->tokens, gb_heap_allocator());
|
array_init(&f->tokens, gb_heap_allocator());
|
||||||
for (;;) {
|
{
|
||||||
Token token = tokenizer_get_token(&f->tokenizer);
|
PROF_SCOPED("Tokenize file");
|
||||||
if (token.kind == Token_Invalid) {
|
for (;;) {
|
||||||
return ParseFile_InvalidToken;
|
Token token = tokenizer_get_token(&f->tokenizer);
|
||||||
}
|
if (token.kind == Token_Invalid) {
|
||||||
array_add(&f->tokens, token);
|
return ParseFile_InvalidToken;
|
||||||
|
}
|
||||||
|
array_add(&f->tokens, token);
|
||||||
|
|
||||||
if (token.kind == Token_EOF) {
|
if (token.kind == Token_EOF) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3044,6 +3047,8 @@ String get_filepath_extension(String path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void parse_file(Parser *p, AstFile *f) {
|
void parse_file(Parser *p, AstFile *f) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
String filepath = f->tokenizer.fullpath;
|
String filepath = f->tokenizer.fullpath;
|
||||||
String base_dir = filepath;
|
String base_dir = filepath;
|
||||||
for (isize i = filepath.len-1; i >= 0; i--) {
|
for (isize i = filepath.len-1; i >= 0; i--) {
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
// #define PROF_TIMINGS
|
||||||
|
|
||||||
|
struct ProfInfo {
|
||||||
|
String name;
|
||||||
|
HashKey hash;
|
||||||
|
i32 count;
|
||||||
|
i64 total_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Profiler {
|
||||||
|
Map<ProfInfo> info; // Key: String
|
||||||
|
isize max_name_len;
|
||||||
|
i64 start_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
gb_global Profiler global_profiler;
|
||||||
|
|
||||||
|
i64 prof_get_timestamp(void) {
|
||||||
|
LARGE_INTEGER counter;
|
||||||
|
QueryPerformanceCounter(&counter);
|
||||||
|
return counter.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prof_init(void) {
|
||||||
|
#if defined(PROF_TIMINGS)
|
||||||
|
map_init(&global_profiler.info, gb_heap_allocator());
|
||||||
|
global_profiler.start_time = prof_get_timestamp();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ProfInfo prof_begin(String name) {
|
||||||
|
ProfInfo info = {};
|
||||||
|
info.name = name;
|
||||||
|
info.hash = hash_pointer(name.text); // NOTE(bill): Requires it to be unique
|
||||||
|
|
||||||
|
info.total_time = prof_get_timestamp();
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prof_end(ProfInfo info) {
|
||||||
|
i64 dt = prof_get_timestamp() - info.total_time;
|
||||||
|
info.total_time = dt;
|
||||||
|
|
||||||
|
auto *found = map_get(&global_profiler.info, info.hash);
|
||||||
|
if (found) {
|
||||||
|
found->count++;
|
||||||
|
found->total_time += info.total_time;
|
||||||
|
} else {
|
||||||
|
info.count++;
|
||||||
|
map_set(&global_profiler.info, info.hash, info);
|
||||||
|
if (global_profiler.max_name_len < info.name.len) {
|
||||||
|
global_profiler.max_name_len = info.name.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ScopedProfInfo {
|
||||||
|
ProfInfo info;
|
||||||
|
ScopedProfInfo(String name) {
|
||||||
|
info = prof_begin(name);
|
||||||
|
}
|
||||||
|
~ScopedProfInfo() {
|
||||||
|
prof_end(info);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(PROF_TIMINGS)
|
||||||
|
#define PROF_SCOPED(msg) ScopedProfInfo scoped_prof_info_##__COUNTER__ = ScopedProfInfo(make_string(cast(u8 *)msg, gb_size_of(msg)-1))
|
||||||
|
#else
|
||||||
|
#define PROF_SCOPED(msg) do {} while (0)
|
||||||
|
#endif
|
||||||
|
#define PROF_PROC() PROF_SCOPED(__FUNCTION__)
|
||||||
|
|
||||||
|
void prof_print_all(void) {
|
||||||
|
#if defined(PROF_TIMINGS)
|
||||||
|
LARGE_INTEGER win32_perf_count_freq = {0};
|
||||||
|
QueryPerformanceFrequency(&win32_perf_count_freq);
|
||||||
|
GB_ASSERT(win32_perf_count_freq.QuadPart != 0);
|
||||||
|
|
||||||
|
gb_printf("Profiler Timings\n");
|
||||||
|
|
||||||
|
i32 string_offset = cast(int)global_profiler.max_name_len;
|
||||||
|
char spaces[] = " ";
|
||||||
|
char dashses[] = "--------------------------------------------------------------------------------";
|
||||||
|
isize pad_len = gb_size_of(spaces)-1;
|
||||||
|
|
||||||
|
isize info_count = global_profiler.info.entries.count;
|
||||||
|
ProfInfo *info_data = gb_alloc_array(gb_heap_allocator(), ProfInfo, info_count);
|
||||||
|
defer (gb_free(gb_heap_allocator(), info_data));
|
||||||
|
for (isize i = 0; i < info_count; i++) {
|
||||||
|
info_data[i] = global_profiler.info.entries[i].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
gb_sort_array(info_data, info_count, gb_i64_cmp(gb_offset_of(ProfInfo, total_time)));
|
||||||
|
|
||||||
|
for (isize i = info_count-1; i >= 0; i--) {
|
||||||
|
auto entry = info_data + i;
|
||||||
|
f64 dt = (1000.0*entry->total_time / cast(f64)win32_perf_count_freq.QuadPart);
|
||||||
|
int pad = global_profiler.max_name_len - entry->name.len;
|
||||||
|
pad = gb_max(pad, 0);
|
||||||
|
gb_printf("%.*s%*.*s - %.3f ms - %.3f us\n",
|
||||||
|
LIT(entry->name),
|
||||||
|
pad, pad, spaces,
|
||||||
|
dt, 1000.0*dt/cast(f64)entry->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
i64 total_time = prof_get_timestamp() - global_profiler.start_time;
|
||||||
|
f64 total_time_ms = (1000.0*total_time / cast(f64)win32_perf_count_freq.QuadPart);
|
||||||
|
|
||||||
|
|
||||||
|
gb_printf("%*.*s\n"
|
||||||
|
"%*.*s %.3f ms\n",
|
||||||
|
global_profiler.max_name_len, global_profiler.max_name_len, dashses,
|
||||||
|
global_profiler.max_name_len, global_profiler.max_name_len, spaces,
|
||||||
|
total_time_ms);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -346,6 +346,8 @@ void advance_to_next_rune(Tokenizer *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
|
TokenizerInitError init_tokenizer(Tokenizer *t, String fullpath) {
|
||||||
|
PROF_PROC();
|
||||||
|
|
||||||
char *c_str = gb_alloc_array(gb_heap_allocator(), char, fullpath.len+1);
|
char *c_str = gb_alloc_array(gb_heap_allocator(), char, fullpath.len+1);
|
||||||
memcpy(c_str, fullpath.text, fullpath.len);
|
memcpy(c_str, fullpath.text, fullpath.len);
|
||||||
c_str[fullpath.len] = '\0';
|
c_str[fullpath.len] = '\0';
|
||||||
|
|||||||
Reference in New Issue
Block a user