mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 23:58:50 +00:00
Minor Entity refactor
This commit is contained in:
+1
-6
@@ -1,10 +1,5 @@
|
|||||||
#import "fmt.odin"
|
#import "fmt.odin"
|
||||||
|
|
||||||
str := "Hellope"
|
|
||||||
|
|
||||||
a: [12]u8
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
v: [4]f32
|
|
||||||
v[0] = 123
|
|
||||||
fmt.println(str, v, v[0], a)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ void destroy_scope(Scope *scope) {
|
|||||||
for_array(i, scope->elements.entries) {
|
for_array(i, scope->elements.entries) {
|
||||||
Entity *e =scope->elements.entries[i].value;
|
Entity *e =scope->elements.entries[i].value;
|
||||||
if (e->kind == Entity_Variable) {
|
if (e->kind == Entity_Variable) {
|
||||||
if (!e->Variable.used) {
|
if (!(e->flags & EntityFlag_Used)) {
|
||||||
#if 0
|
#if 0
|
||||||
warning(e->token, "Unused variable `%.*s`", LIT(e->token.string));
|
warning(e->token, "Unused variable `%.*s`", LIT(e->token.string));
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -198,11 +198,11 @@ void check_var_decl_node(Checker *c, AstNode *node) {
|
|||||||
for (isize i = 0; i < entity_count; i++) {
|
for (isize i = 0; i < entity_count; i++) {
|
||||||
Entity *e = entities[i];
|
Entity *e = entities[i];
|
||||||
GB_ASSERT(e != NULL);
|
GB_ASSERT(e != NULL);
|
||||||
if (e->Variable.visited) {
|
if (e->flags & EntityFlag_Visited) {
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
e->Variable.visited = true;
|
e->flags |= EntityFlag_Visited;
|
||||||
|
|
||||||
if (e->type == NULL)
|
if (e->type == NULL)
|
||||||
e->type = init_type;
|
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);
|
GB_ASSERT(e->type == NULL);
|
||||||
|
|
||||||
if (e->Variable.visited) {
|
if (e->flags & EntityFlag_Visited) {
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e->Variable.visited = true;
|
e->flags |= EntityFlag_Visited;
|
||||||
|
|
||||||
if (type_expr) {
|
if (type_expr) {
|
||||||
Type *t = check_type(c, 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->type == NULL);
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
|
||||||
if (e->Variable.visited) {
|
if (e->flags & EntityFlag_Visited) {
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e->Variable.visited = true;
|
e->flags |= EntityFlag_Visited;
|
||||||
|
|
||||||
if (type_expr != NULL)
|
if (type_expr != NULL)
|
||||||
e->type = check_type(c, 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++) {
|
for (isize i = 0; i < params->variable_count; i++) {
|
||||||
Entity *e = params->variables[i];
|
Entity *e = params->variables[i];
|
||||||
GB_ASSERT(e->kind == Entity_Variable);
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
if (!e->Variable.anonymous) {
|
if (!(e->flags & EntityFlag_Anonymous)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String name = e->token.string;
|
String name = e->token.string;
|
||||||
|
|||||||
+18
-19
@@ -28,10 +28,19 @@ String const entity_strings[] = {
|
|||||||
#undef ENTITY_KIND
|
#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 {
|
struct Entity {
|
||||||
EntityKind kind;
|
EntityKind kind;
|
||||||
Scope * scope;
|
u32 flags;
|
||||||
Token token;
|
Token token;
|
||||||
|
Scope * scope;
|
||||||
Type * type;
|
Type * type;
|
||||||
AstNode * identifier; // Can be NULL
|
AstNode * identifier; // Can be NULL
|
||||||
|
|
||||||
@@ -44,21 +53,11 @@ struct Entity {
|
|||||||
ExactValue value;
|
ExactValue value;
|
||||||
} Constant;
|
} Constant;
|
||||||
struct {
|
struct {
|
||||||
b8 visited;
|
|
||||||
b8 used;
|
|
||||||
b8 anonymous;
|
|
||||||
b8 field;
|
|
||||||
b8 param;
|
|
||||||
|
|
||||||
i32 field_index;
|
i32 field_index;
|
||||||
i32 field_src_index;
|
i32 field_src_index;
|
||||||
} Variable;
|
} Variable;
|
||||||
struct {
|
struct {} TypeName;
|
||||||
b32 used;
|
struct {} Procedure;
|
||||||
} TypeName;
|
|
||||||
struct {
|
|
||||||
b32 used;
|
|
||||||
} Procedure;
|
|
||||||
struct {
|
struct {
|
||||||
BuiltinProcId id;
|
BuiltinProcId id;
|
||||||
} Builtin;
|
} Builtin;
|
||||||
@@ -109,7 +108,7 @@ Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, T
|
|||||||
GB_ASSERT(parent != NULL);
|
GB_ASSERT(parent != NULL);
|
||||||
Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type);
|
Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type);
|
||||||
entity->using_parent = parent;
|
entity->using_parent = parent;
|
||||||
entity->Variable.anonymous = true;
|
entity->flags |= EntityFlag_Anonymous;
|
||||||
return entity;
|
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 *make_entity_param(gbAllocator a, Scope *scope, Token token, Type *type, b32 anonymous) {
|
||||||
Entity *entity = make_entity_variable(a, scope, token, type);
|
Entity *entity = make_entity_variable(a, scope, token, type);
|
||||||
entity->Variable.used = true;
|
entity->flags |= EntityFlag_Used;
|
||||||
entity->Variable.anonymous = cast(b8)anonymous;
|
entity->flags |= EntityFlag_Anonymous*(anonymous != 0);
|
||||||
entity->Variable.param = true;
|
entity->flags |= EntityFlag_Param;
|
||||||
return entity;
|
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 *entity = make_entity_variable(a, scope, token, type);
|
||||||
entity->Variable.field_src_index = field_src_index;
|
entity->Variable.field_src_index = field_src_index;
|
||||||
entity->Variable.field_index = field_src_index;
|
entity->Variable.field_index = field_src_index;
|
||||||
entity->Variable.field = true;
|
entity->flags |= EntityFlag_Field;
|
||||||
entity->Variable.anonymous = cast(b8)anonymous;
|
entity->flags |= EntityFlag_Anonymous*(anonymous != 0);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ b32 check_is_assignable_to_using_subtype(Type *dst, Type *src) {
|
|||||||
if (is_type_struct(src)) {
|
if (is_type_struct(src)) {
|
||||||
for (isize i = 0; i < src->Record.field_count; i++) {
|
for (isize i = 0; i < src->Record.field_count; i++) {
|
||||||
Entity *f = src->Record.fields[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)) {
|
if (are_types_identical(dst, f->type)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ void populate_using_entity_map(Checker *c, AstNode *node, Type *t, Map<Entity *>
|
|||||||
} else {
|
} else {
|
||||||
map_set(entity_map, key, f);
|
map_set(entity_map, key, f);
|
||||||
add_entity(c, c->context.scope, NULL, 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);
|
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;
|
b32 ok = true;
|
||||||
for_array(emi, entity_map.entries) {
|
for_array(emi, entity_map.entries) {
|
||||||
Entity *e = entity_map.entries[emi].value;
|
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 (is_type_indexable(e->type)) {
|
||||||
if (e->identifier != vd->names[0]) {
|
if (e->identifier != vd->names[0]) {
|
||||||
ok = false;
|
ok = false;
|
||||||
@@ -448,7 +448,7 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
|
|||||||
if (ok) {
|
if (ok) {
|
||||||
using_index_expr = fields[field_index-1];
|
using_index_expr = fields[field_index-1];
|
||||||
} else {
|
} 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));
|
error(name_token, "Previous `using` for an index expression `%.*s`", LIT(name_token.string));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -936,7 +936,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Entity_Variable:
|
case Entity_Variable:
|
||||||
e->Variable.used = true;
|
e->flags |= EntityFlag_Used;
|
||||||
if (type == t_invalid) {
|
if (type == t_invalid) {
|
||||||
o->type = t_invalid;
|
o->type = t_invalid;
|
||||||
return;
|
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));
|
GB_ASSERT(is_type_struct(dst_s) || is_type_raw_union(dst_s));
|
||||||
for (isize i = 0; i < dst_s->Record.field_count; i++) {
|
for (isize i = 0; i < dst_s->Record.field_count; i++) {
|
||||||
Entity *f = dst_s->Record.fields[i];
|
Entity *f = dst_s->Record.fields[i];
|
||||||
GB_ASSERT(f->kind == Entity_Variable && f->Variable.field);
|
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
|
||||||
if (f->Variable.anonymous) {
|
if (f->flags & EntityFlag_Anonymous) {
|
||||||
if (are_types_identical(f->type, src_)) {
|
if (are_types_identical(f->type, src_)) {
|
||||||
return f->token.string;
|
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++) {
|
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||||
Entity *f = t->Record.fields[i];
|
Entity *f = t->Record.fields[i];
|
||||||
if (f->kind == Entity_Variable &&
|
if (f->kind == Entity_Variable &&
|
||||||
f->Variable.field && f->Variable.anonymous) {
|
f->flags & (EntityFlag_Anonymous|EntityFlag_Field)) {
|
||||||
if (is_type_indexable(f->type)) {
|
if (is_type_indexable(f->type)) {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,14 +252,16 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
|||||||
ast_node(i, Ident, node);
|
ast_node(i, Ident, node);
|
||||||
e = scope_lookup_entity(c->context.scope, i->string);
|
e = scope_lookup_entity(c->context.scope, i->string);
|
||||||
if (e != NULL && e->kind == Entity_Variable) {
|
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};
|
Operand op_b = {Addressing_Invalid};
|
||||||
check_expr(c, &op_b, lhs);
|
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 ||
|
if (op_b.mode == Addressing_Invalid ||
|
||||||
op_b.type == t_invalid) {
|
op_b.type == t_invalid) {
|
||||||
@@ -829,7 +831,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
// NOTE(bill): Dummy type
|
// NOTE(bill): Dummy type
|
||||||
Type *tag_ptr_type = make_type_pointer(c->allocator, tag_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);
|
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(c, c->context.scope, ms->var, tag_var);
|
||||||
add_entity_use(c, ms->var, tag_var);
|
add_entity_use(c, ms->var, tag_var);
|
||||||
}
|
}
|
||||||
|
|||||||
+32
-34
@@ -94,7 +94,6 @@ enum TypeRecordKind {
|
|||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
TypeKind kind;
|
TypeKind kind;
|
||||||
u32 flags; // See parser.cpp `enum TypeFlag`
|
|
||||||
union {
|
union {
|
||||||
BasicType Basic;
|
BasicType Basic;
|
||||||
struct {
|
struct {
|
||||||
@@ -120,7 +119,7 @@ struct Type {
|
|||||||
// All record types
|
// All record types
|
||||||
// Theses are arrays
|
// Theses are arrays
|
||||||
Entity **fields; // Entity_Variable (otherwise Entity_TypeName if union)
|
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;
|
AstNode *node;
|
||||||
|
|
||||||
union { // NOTE(bill): Reduce size_of Type
|
union { // NOTE(bill): Reduce size_of Type
|
||||||
@@ -141,7 +140,7 @@ struct Type {
|
|||||||
|
|
||||||
// Entity_Constant or Entity_TypeName
|
// Entity_Constant or Entity_TypeName
|
||||||
Entity **other_fields;
|
Entity **other_fields;
|
||||||
isize other_field_count;
|
i32 other_field_count;
|
||||||
} Record;
|
} Record;
|
||||||
struct {
|
struct {
|
||||||
String name;
|
String name;
|
||||||
@@ -150,14 +149,14 @@ struct Type {
|
|||||||
} Named;
|
} Named;
|
||||||
struct {
|
struct {
|
||||||
Entity **variables; // Entity_Variable
|
Entity **variables; // Entity_Variable
|
||||||
isize variable_count;
|
i32 variable_count;
|
||||||
} Tuple;
|
} Tuple;
|
||||||
struct {
|
struct {
|
||||||
Scope *scope;
|
Scope *scope;
|
||||||
Type * params; // Type_Tuple
|
Type * params; // Type_Tuple
|
||||||
Type * results; // Type_Tuple
|
Type * results; // Type_Tuple
|
||||||
isize param_count;
|
i32 param_count;
|
||||||
isize result_count;
|
i32 result_count;
|
||||||
b32 variadic;
|
b32 variadic;
|
||||||
} Proc;
|
} Proc;
|
||||||
};
|
};
|
||||||
@@ -306,34 +305,34 @@ Type *type_deref(Type *t) {
|
|||||||
|
|
||||||
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
#define STR_LIT(x) {cast(u8 *)(x), gb_size_of(x)-1}
|
||||||
gb_global Type basic_types[] = {
|
gb_global Type basic_types[] = {
|
||||||
{Type_Basic, 0, {Basic_Invalid, 0, STR_LIT("invalid type")}},
|
{Type_Basic, {Basic_Invalid, 0, STR_LIT("invalid type")}},
|
||||||
{Type_Basic, 0, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
{Type_Basic, {Basic_bool, BasicFlag_Boolean, STR_LIT("bool")}},
|
||||||
{Type_Basic, 0, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
|
{Type_Basic, {Basic_i8, BasicFlag_Integer, STR_LIT("i8")}},
|
||||||
{Type_Basic, 0, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
{Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
|
||||||
{Type_Basic, 0, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
{Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
|
||||||
{Type_Basic, 0, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
{Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
|
||||||
{Type_Basic, 0, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
{Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
|
||||||
{Type_Basic, 0, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
{Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
|
||||||
{Type_Basic, 0, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
{Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
|
||||||
{Type_Basic, 0, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
{Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
|
||||||
{Type_Basic, 0, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
{Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
|
||||||
{Type_Basic, 0, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
{Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
|
||||||
{Type_Basic, 0, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
|
{Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
|
||||||
{Type_Basic, 0, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
|
{Type_Basic, {Basic_uint, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("uint")}},
|
||||||
{Type_Basic, 0, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
|
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, STR_LIT("rawptr")}},
|
||||||
{Type_Basic, 0, {Basic_string, BasicFlag_String, STR_LIT("string")}},
|
{Type_Basic, {Basic_string, BasicFlag_String, STR_LIT("string")}},
|
||||||
{Type_Basic, 0, {Basic_any, 0, STR_LIT("any")}},
|
{Type_Basic, {Basic_any, 0, STR_LIT("any")}},
|
||||||
{Type_Basic, 0, {Basic_UntypedBool, BasicFlag_Boolean | BasicFlag_Untyped, STR_LIT("untyped bool")}},
|
{Type_Basic, {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, {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, {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, {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, {Basic_UntypedRune, BasicFlag_Integer | BasicFlag_Untyped, STR_LIT("untyped rune")}},
|
||||||
{Type_Basic, 0, {Basic_UntypedNil, BasicFlag_Untyped, STR_LIT("untyped nil")}},
|
{Type_Basic, {Basic_UntypedNil, BasicFlag_Untyped, STR_LIT("untyped nil")}},
|
||||||
};
|
};
|
||||||
|
|
||||||
gb_global Type basic_type_aliases[] = {
|
gb_global Type basic_type_aliases[] = {
|
||||||
{Type_Basic, 0, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}},
|
{Type_Basic, {Basic_byte, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("byte")}},
|
||||||
{Type_Basic, 0, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}},
|
{Type_Basic, {Basic_rune, BasicFlag_Integer, STR_LIT("rune")}},
|
||||||
};
|
};
|
||||||
|
|
||||||
gb_global Type *t_invalid = &basic_types[Basic_Invalid];
|
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)) {
|
} else if (!is_type_enum(type) && !is_type_union(type)) {
|
||||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
for (isize i = 0; i < type->Record.field_count; i++) {
|
||||||
Entity *f = type->Record.fields[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;
|
String str = f->token.string;
|
||||||
if (field_name == str) {
|
if (field_name == str) {
|
||||||
selection_add_index(&sel, i); // HACK(bill): Leaky memory
|
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;
|
return sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->Variable.anonymous) {
|
if (f->flags & EntityFlag_Anonymous) {
|
||||||
isize prev_count = sel.index.count;
|
isize prev_count = sel.index.count;
|
||||||
selection_add_index(&sel, i); // HACK(bill): Leaky memory
|
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) {
|
i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||||
t = base_type(t);
|
t = base_type(t);
|
||||||
|
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Basic: {
|
case Type_Basic: {
|
||||||
GB_ASSERT(is_type_typed(t));
|
GB_ASSERT(is_type_typed(t));
|
||||||
|
|||||||
@@ -1177,6 +1177,8 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) {
|
|||||||
ssa_print_type_name(f, m, v);
|
ssa_print_type_name(f, m, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ssa_fprintf(f, "\n");
|
||||||
|
|
||||||
for_array(member_index, m->members.entries) {
|
for_array(member_index, m->members.entries) {
|
||||||
auto *entry = &m->members.entries[member_index];
|
auto *entry = &m->members.entries[member_index];
|
||||||
ssaValue *v = entry->value;
|
ssaValue *v = entry->value;
|
||||||
@@ -1217,9 +1219,13 @@ void ssa_print_llvm_ir(ssaFileBuffer *f, ssaModule *m) {
|
|||||||
if (g->is_thread_local) {
|
if (g->is_thread_local) {
|
||||||
ssa_fprintf(f, "thread_local ");
|
ssa_fprintf(f, "thread_local ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g->is_private) {
|
||||||
|
ssa_fprintf(f, "private ");
|
||||||
|
}
|
||||||
if (g->is_constant) {
|
if (g->is_constant) {
|
||||||
if (g->is_private) {
|
if (g->is_unnamed_addr) {
|
||||||
ssa_fprintf(f, "private ");
|
ssa_fprintf(f, "unnamed_addr ");
|
||||||
}
|
}
|
||||||
ssa_fprintf(f, "constant ");
|
ssa_fprintf(f, "constant ");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -113,7 +113,6 @@ int main(int argc, char **argv) {
|
|||||||
init_string_buffer_memory();
|
init_string_buffer_memory();
|
||||||
init_global_error_collector();
|
init_global_error_collector();
|
||||||
|
|
||||||
|
|
||||||
String module_dir = get_module_dir();
|
String module_dir = get_module_dir();
|
||||||
|
|
||||||
init_universal_scope();
|
init_universal_scope();
|
||||||
|
|||||||
+23
-13
@@ -226,34 +226,44 @@ AST_NODE_KIND(_StmtEnd, "", struct{}) \
|
|||||||
AST_NODE_KIND(_DeclBegin, "", struct{}) \
|
AST_NODE_KIND(_DeclBegin, "", struct{}) \
|
||||||
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
||||||
AST_NODE_KIND(VarDecl, "variable declaration", struct { \
|
AST_NODE_KIND(VarDecl, "variable declaration", struct { \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
b32 is_using; \
|
b32 is_using; \
|
||||||
AstNodeArray names; \
|
AstNodeArray names; \
|
||||||
AstNode *type; \
|
AstNode * type; \
|
||||||
AstNodeArray values; \
|
AstNodeArray values; \
|
||||||
|
AstNode * note; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ConstDecl, "constant declaration", struct { \
|
AST_NODE_KIND(ConstDecl, "constant declaration", struct { \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
AstNodeArray names; \
|
AstNodeArray names; \
|
||||||
AstNode *type; \
|
AstNode * type; \
|
||||||
AstNodeArray values; \
|
AstNodeArray values; \
|
||||||
|
AstNode * note; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \
|
AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \
|
||||||
AstNode *name; \
|
AstNode *name; \
|
||||||
AstNode *type; \
|
AstNode *type; \
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
String foreign_name; \
|
String foreign_name; \
|
||||||
String link_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 { \
|
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||||
Token token, relpath; \
|
Token token, relpath; \
|
||||||
String fullpath; \
|
String fullpath; \
|
||||||
Token import_name; \
|
Token import_name; \
|
||||||
b32 is_load; \
|
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(_DeclEnd, "", struct{}) \
|
||||||
AST_NODE_KIND(_TypeBegin, "", struct{}) \
|
AST_NODE_KIND(_TypeBegin, "", struct{}) \
|
||||||
AST_NODE_KIND(Parameter, "parameter", struct { \
|
AST_NODE_KIND(Parameter, "parameter", struct { \
|
||||||
|
|||||||
+2
-2
@@ -882,7 +882,7 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ssaValue *ssa_add_using_variable(ssaProcedure *proc, Entity *e) {
|
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;
|
String name = e->token.string;
|
||||||
Entity *parent = e->using_parent;
|
Entity *parent = e->using_parent;
|
||||||
Selection sel = lookup_field(proc->module->allocator, parent->type, name, false);
|
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));
|
ssaValue **found = map_get(&proc->module->values, hash_pointer(e));
|
||||||
if (found) {
|
if (found) {
|
||||||
v = *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);
|
v = ssa_add_using_variable(proc, e);
|
||||||
} else if (e->kind == Entity_ImplicitValue) {
|
} else if (e->kind == Entity_ImplicitValue) {
|
||||||
// TODO(bill): Should a copy be made?
|
// TODO(bill): Should a copy be made?
|
||||||
|
|||||||
+1
-1
@@ -442,7 +442,7 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
Entity *f = t->Record.fields_in_src_order[source_index];
|
Entity *f = t->Record.fields_in_src_order[source_index];
|
||||||
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
|
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
|
||||||
i64 foffset = t->Record.struct_offsets[f->Variable.field_index];
|
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 *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, source_index));
|
||||||
ssaValue *name = ssa_emit_struct_ep(proc, field, 0);
|
ssaValue *name = ssa_emit_struct_ep(proc, field, 0);
|
||||||
|
|||||||
+3
-3
@@ -575,7 +575,7 @@ String lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
|
|||||||
GB_ASSERT(is_type_struct(src));
|
GB_ASSERT(is_type_struct(src));
|
||||||
for (isize i = 0; i < src->Record.field_count; i++) {
|
for (isize i = 0; i < src->Record.field_count; i++) {
|
||||||
Entity *f = src->Record.fields[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)) {
|
if (are_types_identical(dst, f->type)) {
|
||||||
return f->token.string;
|
return f->token.string;
|
||||||
}
|
}
|
||||||
@@ -675,8 +675,8 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
|||||||
|
|
||||||
// float -> float
|
// float -> float
|
||||||
if (is_type_float(src) && is_type_float(dst)) {
|
if (is_type_float(src) && is_type_float(dst)) {
|
||||||
i64 sz = basic_type_sizes[src->Basic.kind];
|
i64 sz = type_size_of(proc->module->sizes, proc->module->allocator, src);
|
||||||
i64 dz = basic_type_sizes[dst->Basic.kind];
|
i64 dz = type_size_of(proc->module->sizes, proc->module->allocator, dst);
|
||||||
ssaConvKind kind = ssaConv_fptrunc;
|
ssaConvKind kind = ssaConv_fptrunc;
|
||||||
if (dz >= sz) {
|
if (dz >= sz) {
|
||||||
kind = ssaConv_fpext;
|
kind = ssaConv_fpext;
|
||||||
|
|||||||
+19
-19
@@ -13,6 +13,7 @@ ssaValue *ssa_alloc_value(gbAllocator a, ssaValueKind kind) {
|
|||||||
ssaValue *ssa_alloc_instr(ssaProcedure *proc, ssaInstrKind kind) {
|
ssaValue *ssa_alloc_instr(ssaProcedure *proc, ssaInstrKind kind) {
|
||||||
ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Instr);
|
ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Instr);
|
||||||
v->Instr.kind = kind;
|
v->Instr.kind = kind;
|
||||||
|
proc->instr_count++;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
ssaDebugInfo *ssa_alloc_debug_info(gbAllocator a, ssaDebugInfoKind kind) {
|
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;
|
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) {
|
ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) {
|
||||||
Scope *scope = NULL;
|
Scope *scope = NULL;
|
||||||
if (node != 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));
|
ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block);
|
||||||
ssaBlock *block = &value->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);
|
array_add(&proc->blocks, block);
|
||||||
|
proc->block_count++;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,7 +434,8 @@ ssaValue *ssa_add_global_string_array(ssaModule *m, String string) {
|
|||||||
ExactValue ev = make_exact_value_string(string);
|
ExactValue ev = make_exact_value_string(string);
|
||||||
Entity *entity = make_entity_constant(a, NULL, token, type, ev);
|
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));
|
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;
|
// g->Global.is_constant = true;
|
||||||
|
|
||||||
ssa_module_add_value(m, entity, g);
|
ssa_module_add_value(m, entity, g);
|
||||||
|
|||||||
+31
-17
@@ -1,4 +1,6 @@
|
|||||||
void ssa_add_operands(Array<ssaValue *> *ops, ssaInstr *i) {
|
// Optimizations for the SSA code
|
||||||
|
|
||||||
|
void ssa_opt_add_operands(Array<ssaValue *> *ops, ssaInstr *i) {
|
||||||
switch (i->kind) {
|
switch (i->kind) {
|
||||||
case ssaInstr_Comment:
|
case ssaInstr_Comment:
|
||||||
break;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssa_optimize_blocks(ssaProcedure *proc) {
|
void ssa_opt_blocks(ssaProcedure *proc) {
|
||||||
ssa_remove_unreachable_blocks(proc);
|
ssa_remove_unreachable_blocks(proc);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
@@ -269,7 +261,7 @@ void ssa_optimize_blocks(ssaProcedure *proc) {
|
|||||||
|
|
||||||
ssa_remove_dead_blocks(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);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||||
defer (gb_temp_arena_memory_end(tmp));
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
@@ -280,7 +272,7 @@ void ssa_build_referrers(ssaProcedure *proc) {
|
|||||||
for_array(j, b->instrs) {
|
for_array(j, b->instrs) {
|
||||||
ssaValue *instr = b->instrs[j];
|
ssaValue *instr = b->instrs[j];
|
||||||
array_clear(&ops);
|
array_clear(&ops);
|
||||||
ssa_add_operands(&ops, &instr->Instr);
|
ssa_opt_add_operands(&ops, &instr->Instr);
|
||||||
for_array(k, ops) {
|
for_array(k, ops) {
|
||||||
ssaValue *op = ops[k];
|
ssaValue *op = ops[k];
|
||||||
if (op == NULL) {
|
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
|
// NOTE(bill): Requires `ssa_opt_blocks` to be called before this
|
||||||
void ssa_build_dom_tree(ssaProcedure *proc) {
|
void ssa_opt_build_dom_tree(ssaProcedure *proc) {
|
||||||
// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
|
// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
|
||||||
|
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
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) {
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-12
@@ -29,18 +29,7 @@ void ssa_end_procedure_body(ssaProcedure *proc) {
|
|||||||
proc->curr_block = proc->decl_block;
|
proc->curr_block = proc->decl_block;
|
||||||
ssa_emit_jump(proc, proc->entry_block);
|
ssa_emit_jump(proc, proc->entry_block);
|
||||||
|
|
||||||
#if 0
|
ssa_opt_proc(proc);
|
||||||
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
|
|
||||||
|
|
||||||
// Number registers
|
// Number registers
|
||||||
i32 reg_index = 0;
|
i32 reg_index = 0;
|
||||||
|
|||||||
+137
-43
@@ -1,44 +1,7 @@
|
|||||||
struct ssaProcedure;
|
struct ssaProcedure;
|
||||||
struct ssaBlock;
|
struct ssaBlock;
|
||||||
struct ssaValue;
|
struct ssaValue;
|
||||||
|
struct ssaDebugInfo;
|
||||||
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<ssaDebugInfo *> procs;
|
|
||||||
} AllProcs;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ssaModule {
|
struct ssaModule {
|
||||||
CheckerInfo * info;
|
CheckerInfo * info;
|
||||||
@@ -130,14 +93,17 @@ struct ssaProcedure {
|
|||||||
AstNode * body;
|
AstNode * body;
|
||||||
u64 tags;
|
u64 tags;
|
||||||
|
|
||||||
isize scope_index;
|
|
||||||
Array<ssaDefer> defer_stmts;
|
Array<ssaDefer> defer_stmts;
|
||||||
Array<ssaBlock *> blocks;
|
Array<ssaBlock *> blocks;
|
||||||
|
i32 scope_index;
|
||||||
ssaBlock * decl_block;
|
ssaBlock * decl_block;
|
||||||
ssaBlock * entry_block;
|
ssaBlock * entry_block;
|
||||||
ssaBlock * curr_block;
|
ssaBlock * curr_block;
|
||||||
ssaTargetList * target_list;
|
ssaTargetList * target_list;
|
||||||
Array<ssaValue *> referrers;
|
Array<ssaValue *> referrers;
|
||||||
|
|
||||||
|
i32 instr_count;
|
||||||
|
i32 block_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SSA_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
|
#define SSA_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
|
||||||
@@ -376,17 +342,18 @@ struct ssaValue {
|
|||||||
Type *type;
|
Type *type;
|
||||||
} Nil;
|
} Nil;
|
||||||
struct {
|
struct {
|
||||||
String name;
|
|
||||||
Type * type;
|
Type * type;
|
||||||
|
String name;
|
||||||
} TypeName;
|
} TypeName;
|
||||||
struct {
|
struct {
|
||||||
b32 is_constant;
|
|
||||||
b32 is_private;
|
|
||||||
b32 is_thread_local;
|
|
||||||
Entity * entity;
|
Entity * entity;
|
||||||
Type * type;
|
Type * type;
|
||||||
ssaValue * value;
|
ssaValue * value;
|
||||||
Array<ssaValue *> referrers;
|
Array<ssaValue *> referrers;
|
||||||
|
b8 is_constant;
|
||||||
|
b8 is_private;
|
||||||
|
b8 is_thread_local;
|
||||||
|
b8 is_unnamed_addr;
|
||||||
} Global;
|
} Global;
|
||||||
struct {
|
struct {
|
||||||
ssaProcedure * parent;
|
ssaProcedure * parent;
|
||||||
@@ -433,6 +400,133 @@ ssaAddr ssa_make_addr_vector(ssaValue *addr, ssaValue *index, AstNode *expr) {
|
|||||||
return v;
|
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<ssaDebugInfo *> procs;
|
||||||
|
} AllProcs;
|
||||||
|
|
||||||
|
|
||||||
|
struct {
|
||||||
|
String name;
|
||||||
|
i32 size;
|
||||||
|
i32 align;
|
||||||
|
ssaDebugEncoding encoding;
|
||||||
|
} BasicType;
|
||||||
|
struct {
|
||||||
|
ssaDebugInfo * return_type;
|
||||||
|
Array<ssaDebugInfo *> 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<ssaDebugInfo *> 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 {
|
struct ssaFileBuffer {
|
||||||
gbVirtualMemory vm;
|
gbVirtualMemory vm;
|
||||||
isize offset;
|
isize offset;
|
||||||
|
|||||||
+2
-1
@@ -128,7 +128,8 @@ String const token_strings[] = {
|
|||||||
|
|
||||||
struct TokenPos {
|
struct TokenPos {
|
||||||
String file;
|
String file;
|
||||||
isize line, column;
|
isize line;
|
||||||
|
isize column;
|
||||||
};
|
};
|
||||||
|
|
||||||
i32 token_pos_cmp(TokenPos a, TokenPos b) {
|
i32 token_pos_cmp(TokenPos a, TokenPos b) {
|
||||||
|
|||||||
Reference in New Issue
Block a user