From 3ec67853e1359015f516aac346760b299d261015 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Sun, 30 Oct 2016 13:20:45 +0000 Subject: [PATCH] Minor `Entity` refactor --- code/demo.odin | 7 +- src/checker/checker.cpp | 2 +- src/checker/decl.cpp | 14 +-- src/checker/entity.cpp | 37 ++++---- src/checker/expr.cpp | 16 ++-- src/checker/stmt.cpp | 8 +- src/checker/types.cpp | 66 +++++++------- src/llvm/ssa_to_text.cpp | 10 ++- src/main.cpp | 1 - src/parser.cpp | 36 +++++--- src/ssa/build.cpp | 4 +- src/ssa/codegen.cpp | 2 +- src/ssa/emit.cpp | 6 +- src/ssa/make.cpp | 38 ++++----- src/ssa/opt.cpp | 48 +++++++---- src/ssa/proc.cpp | 13 +-- src/ssa/ssa.cpp | 180 +++++++++++++++++++++++++++++---------- src/tokenizer.cpp | 3 +- 18 files changed, 299 insertions(+), 192 deletions(-) diff --git a/code/demo.odin b/code/demo.odin index d714907e3..f2844f0b5 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -1,10 +1,5 @@ #import "fmt.odin" -str := "Hellope" - -a: [12]u8 main :: proc() { - v: [4]f32 - v[0] = 123 - fmt.println(str, v, v[0], a) + } diff --git a/src/checker/checker.cpp b/src/checker/checker.cpp index 4beaca6d3..50ac322d3 100644 --- a/src/checker/checker.cpp +++ b/src/checker/checker.cpp @@ -301,7 +301,7 @@ void destroy_scope(Scope *scope) { for_array(i, scope->elements.entries) { Entity *e =scope->elements.entries[i].value; if (e->kind == Entity_Variable) { - if (!e->Variable.used) { + if (!(e->flags & EntityFlag_Used)) { #if 0 warning(e->token, "Unused variable `%.*s`", LIT(e->token.string)); #endif diff --git a/src/checker/decl.cpp b/src/checker/decl.cpp index 3311e5707..63cd6e3ce 100644 --- a/src/checker/decl.cpp +++ b/src/checker/decl.cpp @@ -198,11 +198,11 @@ void check_var_decl_node(Checker *c, AstNode *node) { for (isize i = 0; i < entity_count; i++) { Entity *e = entities[i]; GB_ASSERT(e != NULL); - if (e->Variable.visited) { + if (e->flags & EntityFlag_Visited) { e->type = t_invalid; continue; } - e->Variable.visited = true; + e->flags |= EntityFlag_Visited; if (e->type == NULL) e->type = init_type; @@ -270,11 +270,11 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init_e GB_ASSERT(e->type == NULL); - if (e->Variable.visited) { + if (e->flags & EntityFlag_Visited) { e->type = t_invalid; return; } - e->Variable.visited = true; + e->flags |= EntityFlag_Visited; if (type_expr) { Type *t = check_type(c, type_expr); @@ -463,11 +463,11 @@ void check_var_decl(Checker *c, Entity *e, Entity **entities, isize entity_count GB_ASSERT(e->type == NULL); GB_ASSERT(e->kind == Entity_Variable); - if (e->Variable.visited) { + if (e->flags & EntityFlag_Visited) { e->type = t_invalid; return; } - e->Variable.visited = true; + e->flags |= EntityFlag_Visited; if (type_expr != NULL) e->type = check_type(c, type_expr, NULL); @@ -511,7 +511,7 @@ void check_proc_body(Checker *c, Token token, DeclInfo *decl, Type *type, AstNod for (isize i = 0; i < params->variable_count; i++) { Entity *e = params->variables[i]; GB_ASSERT(e->kind == Entity_Variable); - if (!e->Variable.anonymous) { + if (!(e->flags & EntityFlag_Anonymous)) { continue; } String name = e->token.string; diff --git a/src/checker/entity.cpp b/src/checker/entity.cpp index 3391a769f..3a0bee3df 100644 --- a/src/checker/entity.cpp +++ b/src/checker/entity.cpp @@ -28,10 +28,19 @@ String const entity_strings[] = { #undef ENTITY_KIND }; +enum EntityFlag : u32 { + EntityFlag_Visited = 1<<0, + EntityFlag_Used = 1<<1, + EntityFlag_Anonymous = 1<<2, + EntityFlag_Field = 1<<3, + EntityFlag_Param = 1<<4, +}; + struct Entity { EntityKind kind; - Scope * scope; + u32 flags; Token token; + Scope * scope; Type * type; AstNode * identifier; // Can be NULL @@ -44,21 +53,11 @@ struct Entity { ExactValue value; } Constant; struct { - b8 visited; - b8 used; - b8 anonymous; - b8 field; - b8 param; - i32 field_index; i32 field_src_index; } Variable; - struct { - b32 used; - } TypeName; - struct { - b32 used; - } Procedure; + struct {} TypeName; + struct {} Procedure; struct { BuiltinProcId id; } Builtin; @@ -109,7 +108,7 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T GB_ASSERT(parent != NULL); Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type); entity->using_parent = parent; - entity->Variable.anonymous = true; + entity->flags |= EntityFlag_Anonymous; return entity; } @@ -127,9 +126,9 @@ Entity *make_entity_type_name(gbAllocator a, Scope *scope, Token token, Type *ty Entity *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, b32 anonymous) { Entity *entity = make_entity_variable(a, scope, token, type); - entity->Variable.used = true; - entity->Variable.anonymous = cast(b8)anonymous; - entity->Variable.param = true; + entity->flags |= EntityFlag_Used; + entity->flags |= EntityFlag_Anonymous*(anonymous != 0); + entity->flags |= EntityFlag_Param; return entity; } @@ -137,8 +136,8 @@ Entity *make_entity_field(gbAllocator a, Scope *scope, Token token, Type *type, Entity *entity = make_entity_variable(a, scope, token, type); entity->Variable.field_src_index = field_src_index; entity->Variable.field_index = field_src_index; - entity->Variable.field = true; - entity->Variable.anonymous = cast(b8)anonymous; + entity->flags |= EntityFlag_Field; + entity->flags |= EntityFlag_Anonymous*(anonymous != 0); return entity; } diff --git a/src/checker/expr.cpp b/src/checker/expr.cpp index 9024d3c9e..50367e027 100644 --- a/src/checker/expr.cpp +++ b/src/checker/expr.cpp @@ -26,7 +26,7 @@ b32 check_is_assignable_to_using_subtype(Type *dst, Type *src) { if (is_type_struct(src)) { for (isize i = 0; i < src->Record.field_count; i++) { Entity *f = src->Record.fields[i]; - if (f->kind == Entity_Variable && f->Variable.anonymous) { + if (f->kind == Entity_Variable && (f->flags & EntityFlag_Anonymous)) { if (are_types_identical(dst, f->type)) { return true; } @@ -231,7 +231,7 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map } else { map_set(entity_map, key, f); add_entity(c, c->context.scope, NULL, f); - if (f->Variable.anonymous) { + if (f->flags & EntityFlag_Anonymous) { populate_using_entity_map(c, node, f->type, entity_map); } } @@ -435,7 +435,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, b32 ok = true; for_array(emi, entity_map.entries) { Entity *e = entity_map.entries[emi].value; - if (e->kind == Entity_Variable && e->Variable.anonymous) { + if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) { if (is_type_indexable(e->type)) { if (e->identifier != vd->names[0]) { ok = false; @@ -448,7 +448,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls, if (ok) { using_index_expr = fields[field_index-1]; } else { - fields[field_index-1]->Variable.anonymous = false; + fields[field_index-1]->flags &= ~EntityFlag_Anonymous; error(name_token, "Previous `using` for an index expression `%.*s`", LIT(name_token.string)); } } else { @@ -936,7 +936,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl break; case Entity_Variable: - e->Variable.used = true; + e->flags |= EntityFlag_Used; if (type == t_invalid) { o->type = t_invalid; return; @@ -1748,8 +1748,8 @@ String check_down_cast_name(Type *dst_, Type *src_) { GB_ASSERT(is_type_struct(dst_s) || is_type_raw_union(dst_s)); for (isize i = 0; i < dst_s->Record.field_count; i++) { Entity *f = dst_s->Record.fields[i]; - GB_ASSERT(f->kind == Entity_Variable && f->Variable.field); - if (f->Variable.anonymous) { + GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); + if (f->flags & EntityFlag_Anonymous) { if (are_types_identical(f->type, src_)) { return f->token.string; } @@ -3490,7 +3490,7 @@ Entity *find_using_index_expr(Type *t) { for (isize i = 0; i < t->Record.field_count; i++) { Entity *f = t->Record.fields[i]; if (f->kind == Entity_Variable && - f->Variable.field && f->Variable.anonymous) { + f->flags & (EntityFlag_Anonymous|EntityFlag_Field)) { if (is_type_indexable(f->type)) { return f; } diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index a4647fc29..54ae39ba3 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -252,14 +252,16 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) { ast_node(i, Ident, node); e = scope_lookup_entity(c->context.scope, i->string); if (e != NULL && e->kind == Entity_Variable) { - used = e->Variable.used; // TODO(bill): Make backup just in case + used = (e->flags & EntityFlag_Used) != 0; // TODO(bill): Make backup just in case } } Operand op_b = {Addressing_Invalid}; check_expr(c, &op_b, lhs); - if (e) e->Variable.used = used; + if (e) { + e->flags |= EntityFlag_Used*used; + } if (op_b.mode == Addressing_Invalid || op_b.type == t_invalid) { @@ -829,7 +831,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { // NOTE(bill): Dummy type Type *tag_ptr_type = make_type_pointer(c->allocator, tag_type); Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, ms->var->Ident, tag_ptr_type); - tag_var->Variable.used = true; + tag_var->flags |= EntityFlag_Used; add_entity(c, c->context.scope, ms->var, tag_var); add_entity_use(c, ms->var, tag_var); } diff --git a/src/checker/types.cpp b/src/checker/types.cpp index e216e556d..6cbd7b237 100644 --- a/src/checker/types.cpp +++ b/src/checker/types.cpp @@ -94,7 +94,6 @@ enum TypeRecordKind { struct Type { TypeKind kind; - u32 flags; // See parser.cpp `enum TypeFlag` union { BasicType Basic; struct { @@ -120,7 +119,7 @@ struct Type { // All record types // Theses are arrays Entity **fields; // Entity_Variable (otherwise Entity_TypeName if union) - isize field_count; // == offset_count is struct + i32 field_count; // == offset_count is struct AstNode *node; union { // NOTE(bill): Reduce size_of Type @@ -141,7 +140,7 @@ struct Type { // Entity_Constant or Entity_TypeName Entity **other_fields; - isize other_field_count; + i32 other_field_count; } Record; struct { String name; @@ -150,14 +149,14 @@ struct Type { } Named; struct { Entity **variables; // Entity_Variable - isize variable_count; + i32 variable_count; } Tuple; struct { Scope *scope; Type * params; // Type_Tuple Type * results; // Type_Tuple - isize param_count; - isize result_count; + i32 param_count; + i32 result_count; b32 variadic; } Proc; }; @@ -306,34 +305,34 @@ Type *type_deref(Type *t) { #define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1} gb_global Type basic_types[] = { - {Type_Basic, 0, {Basic_Invalid, 0, STR_LIT("invalid type")}}, - {Type_Basic, 0, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}}, - {Type_Basic, 0, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}}, - {Type_Basic, 0, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}}, - {Type_Basic, 0, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}}, - {Type_Basic, 0, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}}, - {Type_Basic, 0, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}}, - {Type_Basic, 0, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}}, - {Type_Basic, 0, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}}, - {Type_Basic, 0, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}}, - {Type_Basic, 0, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}}, - {Type_Basic, 0, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}}, - {Type_Basic, 0, {Basic_int, BasicFlag_Integer, STR_LIT("int")}}, - {Type_Basic, 0, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}}, - {Type_Basic, 0, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}}, - {Type_Basic, 0, {Basic_string, BasicFlag_String, STR_LIT("string")}}, - {Type_Basic, 0, {Basic_any, 0, STR_LIT("any")}}, - {Type_Basic, 0, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}}, - {Type_Basic, 0, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}}, - {Type_Basic, 0, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}}, - {Type_Basic, 0, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}}, - {Type_Basic, 0, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}}, - {Type_Basic, 0, {Basic_UntypedNil, BasicFlag_Untyped, STR_LIT("untyped nil")}}, + {Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}}, + {Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}}, + {Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}}, + {Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}}, + {Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}}, + {Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}}, + {Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}}, + {Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}}, + {Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}}, + {Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}}, + {Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}}, + {Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}}, + {Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}}, + {Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}}, + {Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}}, + {Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}}, + {Type_Basic, {Basic_any, 0, STR_LIT("any")}}, + {Type_Basic, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}}, + {Type_Basic, {Basic_UntypedInteger, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped integer")}}, + {Type_Basic, {Basic_UntypedFloat, BasicFlag_Float | BasicFlag_Untyped, STR_LIT("untyped float")}}, + {Type_Basic, {Basic_UntypedString, BasicFlag_String | BasicFlag_Untyped, STR_LIT("untyped string")}}, + {Type_Basic, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}}, + {Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, STR_LIT("untyped nil")}}, }; gb_global Type basic_type_aliases[] = { - {Type_Basic, 0, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}}, - {Type_Basic, 0, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}}, + {Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}}, + {Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}}, }; gb_global Type *t_invalid = &basic_types[Basic_Invalid]; @@ -970,7 +969,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ } else if (!is_type_enum(type) && !is_type_union(type)) { for (isize i = 0; i < type->Record.field_count; i++) { Entity *f = type->Record.fields[i]; - GB_ASSERT(f->kind == Entity_Variable && f->Variable.field); + GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); String str = f->token.string; if (field_name == str) { selection_add_index(&sel, i); // HACK(bill): Leaky memory @@ -978,7 +977,7 @@ Selection lookup_field(gbAllocator a, Type *type_, String field_name, b32 is_typ return sel; } - if (f->Variable.anonymous) { + if (f->flags & EntityFlag_Anonymous) { isize prev_count = sel.index.count; selection_add_index(&sel, i); // HACK(bill): Leaky memory @@ -1121,7 +1120,6 @@ b32 type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) { i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) { t = base_type(t); - switch (t->kind) { case Type_Basic: { GB_ASSERT(is_type_typed(t)); diff --git a/src/llvm/ssa_to_text.cpp b/src/llvm/ssa_to_text.cpp index 71cd8baf4..efa79f012 100644 --- a/src/llvm/ssa_to_text.cpp +++ b/src/llvm/ssa_to_text.cpp @@ -1177,6 +1177,8 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) { ssa_print_type_name(f, m, v); } + ssa_fprintf(f, "\n"); + for_array(member_index, m->members.entries) { auto *entry = &m->members.entries[member_index]; ssaValue *v = entry->value; @@ -1217,9 +1219,13 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) { if (g->is_thread_local) { ssa_fprintf(f, "thread_local "); } + + if (g->is_private) { + ssa_fprintf(f, "private "); + } if (g->is_constant) { - if (g->is_private) { - ssa_fprintf(f, "private "); + if (g->is_unnamed_addr) { + ssa_fprintf(f, "unnamed_addr "); } ssa_fprintf(f, "constant "); } else { diff --git a/src/main.cpp b/src/main.cpp index ac326eeab..8098182e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -113,7 +113,6 @@ int main(int argc, char **argv) { init_string_buffer_memory(); init_global_error_collector(); - String module_dir = get_module_dir(); init_universal_scope(); diff --git a/src/parser.cpp b/src/parser.cpp index c36fbf85a..4c390932b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -226,34 +226,44 @@ AST_NODE_KIND(_StmtEnd, "", struct{}) \ AST_NODE_KIND(_DeclBegin, "", struct{}) \ AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \ AST_NODE_KIND(VarDecl, "variable declaration", struct { \ - u64 tags; \ - b32 is_using; \ + u64 tags; \ + b32 is_using; \ AstNodeArray names; \ - AstNode *type; \ + AstNode * type; \ AstNodeArray values; \ + AstNode * note; \ }) \ AST_NODE_KIND(ConstDecl, "constant declaration", struct { \ - u64 tags; \ + u64 tags; \ AstNodeArray names; \ - AstNode *type; \ + AstNode * type; \ AstNodeArray values; \ + AstNode * note; \ }) \ AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \ - AstNode *name; \ - AstNode *type; \ - AstNode *body; \ - u64 tags; \ - String foreign_name; \ - String link_name; \ + AstNode *name; \ + AstNode *type; \ + AstNode *body; \ + u64 tags; \ + String foreign_name; \ + String link_name; \ + AstNode *note; \ + }) \ + AST_NODE_KIND(TypeDecl, "type declaration", struct { \ + Token token; \ + AstNode *name, *type; \ + AstNode *note; \ }) \ - AST_NODE_KIND(TypeDecl, "type declaration", struct { Token token; AstNode *name, *type; }) \ AST_NODE_KIND(ImportDecl, "import declaration", struct { \ Token token, relpath; \ String fullpath; \ Token import_name; \ b32 is_load; \ + AstNode *note; \ + }) \ + AST_NODE_KIND(ForeignSystemLibrary, "foreign system library", struct { \ + Token token, filepath; \ }) \ - AST_NODE_KIND(ForeignSystemLibrary, "foreign system library", struct { Token token, filepath; }) \ AST_NODE_KIND(_DeclEnd, "", struct{}) \ AST_NODE_KIND(_TypeBegin, "", struct{}) \ AST_NODE_KIND(Parameter, "parameter", struct { \ diff --git a/src/ssa/build.cpp b/src/ssa/build.cpp index 31ced6a76..61d8bca34 100644 --- a/src/ssa/build.cpp +++ b/src/ssa/build.cpp @@ -882,7 +882,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) { } ssaValue *ssa_add_using_variable(ssaProcedure *proc, Entity *e) { - GB_ASSERT(e->kind == Entity_Variable && e->Variable.anonymous); + GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous); String name = e->token.string; Entity *parent = e->using_parent; Selection sel = lookup_field(proc->module->allocator, parent->type, name, false); @@ -917,7 +917,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) { ssaValue **found = map_get(&proc->module->values, hash_pointer(e)); if (found) { v = *found; - } else if (e->kind == Entity_Variable && e->Variable.anonymous) { + } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Anonymous) { v = ssa_add_using_variable(proc, e); } else if (e->kind == Entity_ImplicitValue) { // TODO(bill): Should a copy be made? diff --git a/src/ssa/codegen.cpp b/src/ssa/codegen.cpp index fbf9bb0c8..f5784057b 100644 --- a/src/ssa/codegen.cpp +++ b/src/ssa/codegen.cpp @@ -442,7 +442,7 @@ void ssa_gen_tree(ssaGen *s) { Entity *f = t->Record.fields_in_src_order[source_index]; ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type); i64 foffset = t->Record.struct_offsets[f->Variable.field_index]; - GB_ASSERT(f->kind == Entity_Variable && f->Variable.field); + GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field); ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, source_index)); ssaValue *name = ssa_emit_struct_ep(proc, field, 0); diff --git a/src/ssa/emit.cpp b/src/ssa/emit.cpp index a5b4f7917..86c1d7e65 100644 --- a/src/ssa/emit.cpp +++ b/src/ssa/emit.cpp @@ -575,7 +575,7 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) { GB_ASSERT(is_type_struct(src)); for (isize i = 0; i < src->Record.field_count; i++) { Entity *f = src->Record.fields[i]; - if (f->kind == Entity_Variable && f->Variable.anonymous) { + if (f->kind == Entity_Variable && f->flags & EntityFlag_Anonymous) { if (are_types_identical(dst, f->type)) { return f->token.string; } @@ -675,8 +675,8 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg // float -> float if (is_type_float(src) && is_type_float(dst)) { - i64 sz = basic_type_sizes[src->Basic.kind]; - i64 dz = basic_type_sizes[dst->Basic.kind]; + i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src); + i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst); ssaConvKind kind = ssaConv_fptrunc; if (dz >= sz) { kind = ssaConv_fpext; diff --git a/src/ssa/make.cpp b/src/ssa/make.cpp index 1d9a29b9f..76f4c3416 100644 --- a/src/ssa/make.cpp +++ b/src/ssa/make.cpp @@ -13,6 +13,7 @@ ssaValue *ssa_alloc_value(gbAllocator a, ssaValueKind kind) { ssaValue *ssa_alloc_instr(ssaProcedure *proc, ssaInstrKind kind) { ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Instr); v->Instr.kind = kind; + proc->instr_count++; return v; } ssaDebugInfo *ssa_alloc_debug_info(gbAllocator a, ssaDebugInfoKind kind) { @@ -330,22 +331,6 @@ ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Entity *entity, return v; } -ssaValue *ssa_make_value_block(ssaProcedure *proc, AstNode *node, Scope *scope, String label) { - ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block); - v->Block.label = label; - v->Block.node = node; - v->Block.scope = scope; - v->Block.parent = proc; - - array_init(&v->Block.instrs, heap_allocator()); - array_init(&v->Block.locals, heap_allocator()); - - array_init(&v->Block.preds, heap_allocator()); - array_init(&v->Block.succs, heap_allocator()); - - return v; -} - ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) { Scope *scope = NULL; if (node != NULL) { @@ -357,9 +342,23 @@ ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) { } } - ssaValue *value = ssa_make_value_block(proc, node, scope, make_string(label)); - ssaBlock *block = &value->Block; + ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block); + v->Block.label = make_string(label); + v->Block.node = node; + v->Block.scope = scope; + v->Block.parent = proc; + + array_init(&v->Block.instrs, heap_allocator()); + array_init(&v->Block.locals, heap_allocator()); + + array_init(&v->Block.preds, heap_allocator()); + array_init(&v->Block.succs, heap_allocator()); + + ssaBlock *block = &v->Block; + array_add(&proc->blocks, block); + proc->block_count++; + return block; } @@ -435,7 +434,8 @@ ssaValue *ssa_add_global_string_array(ssaModule *m, String string) { ExactValue ev = make_exact_value_string(string); Entity *entity = make_entity_constant(a, NULL, token, type, ev); ssaValue *g = ssa_make_value_global(a, entity, ssa_add_module_constant(m, type, ev)); - g->Global.is_private = true; + g->Global.is_private = true; + // g->Global.is_unnamed_addr = true; // g->Global.is_constant = true; ssa_module_add_value(m, entity, g); diff --git a/src/ssa/opt.cpp b/src/ssa/opt.cpp index 3f3e91dee..c1b1d0f76 100644 --- a/src/ssa/opt.cpp +++ b/src/ssa/opt.cpp @@ -1,4 +1,6 @@ -void ssa_add_operands(Array *ops, ssaInstr *i) { +// Optimizations for the SSA code + +void ssa_opt_add_operands(Array *ops, ssaInstr *i) { switch (i->kind) { case ssaInstr_Comment: break; @@ -110,16 +112,6 @@ b32 ssa_block_has_phi(ssaBlock *b) { -void ssa_optimize_blocks(ssaProcedure *proc); -void ssa_build_referrers(ssaProcedure *proc); -void ssa_build_dom_tree (ssaProcedure *proc); -void ssa_opt_mem2reg (ssaProcedure *proc); - - - - - - @@ -245,7 +237,7 @@ b32 ssa_opt_block_fusion(ssaProcedure *proc, ssaBlock *a) { return true; } -void ssa_optimize_blocks(ssaProcedure *proc) { +void ssa_opt_blocks(ssaProcedure *proc) { ssa_remove_unreachable_blocks(proc); #if 1 @@ -269,7 +261,7 @@ void ssa_optimize_blocks(ssaProcedure *proc) { ssa_remove_dead_blocks(proc); } -void ssa_build_referrers(ssaProcedure *proc) { +void ssa_opt_build_referrers(ssaProcedure *proc) { gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena); defer (gb_temp_arena_memory_end(tmp)); @@ -280,7 +272,7 @@ void ssa_build_referrers(ssaProcedure *proc) { for_array(j, b->instrs) { ssaValue *instr = b->instrs[j]; array_clear(&ops); - ssa_add_operands(&ops, &instr->Instr); + ssa_opt_add_operands(&ops, &instr->Instr); for_array(k, ops) { ssaValue *op = ops[k]; if (op == NULL) { @@ -358,8 +350,8 @@ void ssa_number_dom_tree(ssaBlock *v, i32 pre, i32 post, i32 *pre_out, i32 *post } -// NOTE(bill): Requires `ssa_optimize_blocks` to be called before this -void ssa_build_dom_tree(ssaProcedure *proc) { +// NOTE(bill): Requires `ssa_opt_blocks` to be called before this +void ssa_opt_build_dom_tree(ssaProcedure *proc) { // Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena); @@ -448,5 +440,27 @@ void ssa_build_dom_tree(ssaProcedure *proc) { } void ssa_opt_mem2reg(ssaProcedure *proc) { - // TODO(bill): + // TODO(bill): ssa_opt_mem2reg +} + + +void ssa_opt_proc(ssaProcedure *proc) { + ssa_opt_blocks(proc); +#if 1 + ssa_opt_build_referrers(proc); + ssa_opt_build_dom_tree(proc); + + // TODO(bill): ssa optimization + // [ ] cse (common-subexpression) elim + // [ ] copy elim + // [ ] dead code elim + // [ ] dead store/load elim + // [ ] phi elim + // [ ] short circuit elim + // [ ] bounds check elim + // [ ] lift/mem2reg + // [ ] lift/mem2reg + + ssa_opt_mem2reg(proc); +#endif } diff --git a/src/ssa/proc.cpp b/src/ssa/proc.cpp index 6d9c75b5d..262c44972 100644 --- a/src/ssa/proc.cpp +++ b/src/ssa/proc.cpp @@ -29,18 +29,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) { proc->curr_block = proc->decl_block; ssa_emit_jump(proc, proc->entry_block); -#if 0 - ssa_optimize_blocks(proc); - ssa_build_referrers(proc); - ssa_build_dom_tree(proc); - - // TODO(bill): mem2reg optimization - // [ ] Local never loaded? Eliminate - // [ ] Local never stored? Replace all loads with `Nil` - // [ ] Local stored once? Replace loads with dominating store - // [ ] Convert to phi nodes - ssa_opt_mem2reg(proc); -#endif + ssa_opt_proc(proc); // Number registers i32 reg_index = 0; diff --git a/src/ssa/ssa.cpp b/src/ssa/ssa.cpp index 8f6e68af8..9e1ff1ecc 100644 --- a/src/ssa/ssa.cpp +++ b/src/ssa/ssa.cpp @@ -1,44 +1,7 @@ struct ssaProcedure; struct ssaBlock; struct ssaValue; - -enum ssaDebugInfoKind { - ssaDebugInfo_Invalid, - - ssaDebugInfo_CompileUnit, - ssaDebugInfo_File, - ssaDebugInfo_Proc, - ssaDebugInfo_AllProcs, - - ssaDebugInfo_Count, -}; - -struct ssaDebugInfo { - ssaDebugInfoKind kind; - i32 id; - - union { - struct { - AstFile * file; - String producer; - ssaDebugInfo *all_procs; - } CompileUnit; - struct { - AstFile *file; - String filename; - String directory; - } File; - struct { - Entity * entity; - String name; - ssaDebugInfo *file; - TokenPos pos; - } Proc; - struct { - Array procs; - } AllProcs; - }; -}; +struct ssaDebugInfo; struct ssaModule { CheckerInfo * info; @@ -130,14 +93,17 @@ struct ssaProcedure { AstNode * body; u64 tags; - isize scope_index; Array defer_stmts; Array blocks; + i32 scope_index; ssaBlock * decl_block; ssaBlock * entry_block; ssaBlock * curr_block; ssaTargetList * target_list; Array referrers; + + i32 instr_count; + i32 block_count; }; #define SSA_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" @@ -376,17 +342,18 @@ struct ssaValue { Type *type; } Nil; struct { - String name; Type * type; + String name; } TypeName; struct { - b32 is_constant; - b32 is_private; - b32 is_thread_local; Entity * entity; Type * type; ssaValue * value; Array referrers; + b8 is_constant; + b8 is_private; + b8 is_thread_local; + b8 is_unnamed_addr; } Global; struct { ssaProcedure * parent; @@ -433,6 +400,133 @@ ssaAddr ssa_make_addr_vector(ssaValue *addr, ssaValue *index, AstNode *expr) { return v; } + + +enum ssaDebugEncoding { + ssaDebugBasicEncoding_Invalid = 0, + + ssaDebugBasicEncoding_address = 1, + ssaDebugBasicEncoding_boolean = 2, + ssaDebugBasicEncoding_float = 3, + ssaDebugBasicEncoding_signed = 4, + ssaDebugBasicEncoding_signed_char = 5, + ssaDebugBasicEncoding_unsigned = 6, + ssaDebugBasicEncoding_unsigned_char = 7, + + ssaDebugBasicEncoding_member = 13, + ssaDebugBasicEncoding_pointer_type = 15, + ssaDebugBasicEncoding_typedef = 22, + + ssaDebugBasicEncoding_array_type = 1, + ssaDebugBasicEncoding_enumeration_type = 4, + ssaDebugBasicEncoding_structure_type = 19, + ssaDebugBasicEncoding_union_type = 23, + +}; + +enum ssaDebugInfoKind { + ssaDebugInfo_Invalid, + + ssaDebugInfo_CompileUnit, + ssaDebugInfo_File, + ssaDebugInfo_Scope, + ssaDebugInfo_Proc, + ssaDebugInfo_AllProcs, + + ssaDebugInfo_BasicType, // basic types + ssaDebugInfo_ProcType, + ssaDebugInfo_DerivedType, // pointer, typedef + ssaDebugInfo_CompositeType, // array, struct, enum, (raw_)union + ssaDebugInfo_Enumerator, // For ssaDebugInfo_CompositeType if enum + ssaDebugInfo_GlobalVariable, + ssaDebugInfo_LocalVariable, + + + ssaDebugInfo_Count, +}; + +struct ssaDebugInfo { + ssaDebugInfoKind kind; + i32 id; + + union { + struct { + AstFile * file; + String producer; + ssaDebugInfo *all_procs; + } CompileUnit; + struct { + AstFile *file; + String filename; + String directory; + } File; + struct { + ssaDebugInfo *parent; + ssaDebugInfo *file; + TokenPos pos; + Scope * scope; // Actual scope + } Scope; + struct { + Entity * entity; + String name; + ssaDebugInfo *file; + TokenPos pos; + } Proc; + struct { + Array procs; + } AllProcs; + + + struct { + String name; + i32 size; + i32 align; + ssaDebugEncoding encoding; + } BasicType; + struct { + ssaDebugInfo * return_type; + Array param_types; + } ProcType; + struct { + ssaDebugInfo * base_type; + ssaDebugEncoding encoding; + } DerivedType; + struct { + ssaDebugEncoding encoding; + String name; + String identifier; + ssaDebugInfo * file; + TokenPos pos; + i32 size; + i32 align; + Array elements; + } CompositeType; + struct { + String name; + i64 value; + } Enumerator; + struct { + String name; + String linkage_name; + ssaDebugInfo *scope; + ssaDebugInfo *file; + TokenPos pos; + ssaValue *variable; + ssaDebugInfo *declaration; + } GlobalVariable; + struct { + String name; + ssaDebugInfo *scope; + ssaDebugInfo *file; + TokenPos pos; + i32 arg; // Non-zero if proc parameter + ssaDebugInfo *type; + } LocalVariable; + }; +}; + + + struct ssaFileBuffer { gbVirtualMemory vm; isize offset; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 02003d4af..4e0cc5791 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -128,7 +128,8 @@ String const token_strings[] = { struct TokenPos { String file; - isize line, column; + isize line; + isize column; }; i32 token_pos_cmp(TokenPos a, TokenPos b) {