diff options
| author | Ginger Bill <bill@gingerbill.org> | 2017-04-23 18:03:29 +0100 |
|---|---|---|
| committer | Ginger Bill <bill@gingerbill.org> | 2017-04-23 18:03:29 +0100 |
| commit | 822bb51b55bc62f9d406db80e9d5a71d3a300a19 (patch) | |
| tree | 72f50fc5005ab77c82636a73c8f09e9a328ec3c2 /src | |
| parent | c2fa79012ea01ad508083f13f86d2b6c8f5045da (diff) | |
Swap memory layout of `any`
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_expr.c | 30 | ||||
| -rw-r--r-- | src/ir.c | 38 | ||||
| -rw-r--r-- | src/ir_print.c | 4 | ||||
| -rw-r--r-- | src/parser.c | 4 | ||||
| -rw-r--r-- | src/types.c | 24 |
5 files changed, 56 insertions, 44 deletions
diff --git a/src/check_expr.c b/src/check_expr.c index 169798da5..882d467e4 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -86,10 +86,10 @@ bool check_is_assignable_to_using_subtype(Type *dst, Type *src) { src_is_ptr = src != prev_src; src = base_type(src); - if (is_type_struct(src)) { + if (is_type_struct(src) || is_type_union(src)) { for (isize i = 0; i < src->Record.field_count; i++) { Entity *f = src->Record.fields[i]; - if (f->kind == Entity_Variable && (f->flags & EntityFlag_Using)) { + if (f->kind == Entity_Variable && (f->flags & EntityFlag_Using) != 0) { if (are_types_identical(dst, f->type)) { return true; } @@ -203,6 +203,7 @@ i64 check_distance_between_types(Checker *c, Operand *operand, Type *type) { } } + if (is_type_any(dst)) { // NOTE(bill): Anything can cast to `Any` add_type_info_type(c, s); @@ -442,8 +443,9 @@ isize check_fields(Checker *c, AstNode *node, AstNodeArray decls, // TODO(bill): Inline sorting procedure? gb_global gbAllocator __checker_allocator = {0}; -GB_COMPARE_PROC(cmp_struct_entity_size) { +GB_COMPARE_PROC(cmp_reorder_struct_fields) { // Rule: + // `using` over non-`using` // Biggest to smallest alignment // if same alignment: biggest to smallest size // if same size: order by source order @@ -453,19 +455,25 @@ GB_COMPARE_PROC(cmp_struct_entity_size) { GB_ASSERT(y != NULL); GB_ASSERT(x->kind == Entity_Variable); GB_ASSERT(y->kind == Entity_Variable); + bool xu = (x->flags & EntityFlag_Using) != 0; + bool yu = (y->flags & EntityFlag_Using) != 0; i64 xa = type_align_of(__checker_allocator, x->type); i64 ya = type_align_of(__checker_allocator, y->type); i64 xs = type_size_of(__checker_allocator, x->type); i64 ys = type_size_of(__checker_allocator, y->type); - if (xa == ya) { - if (xs == ys) { - i32 diff = x->Variable.field_index - y->Variable.field_index; - return diff < 0 ? -1 : diff > 0; - } + if (xu != yu) { + return xu ? -1 : +1; + } + + if (xa != ya) { + return xa > ya ? -1 : xa < ya; + } + if (xs != ys) { return xs > ys ? -1 : xs < ys; } - return xa > ya ? -1 : xa < ya; + i32 diff = x->Variable.field_index - y->Variable.field_index; + return diff < 0 ? -1 : diff > 0; } Entity *make_names_field_for_record(Checker *c, Scope *scope) { @@ -513,7 +521,7 @@ void check_struct_type(Checker *c, Type *struct_type, AstNode *node) { // TODO(bill): Probably make an inline sorting procedure rather than use global variables __checker_allocator = c->allocator; // NOTE(bill): compound literal order must match source not layout - gb_sort_array(reordered_fields, field_count, cmp_struct_entity_size); + gb_sort_array(reordered_fields, field_count, cmp_reorder_struct_fields); for (isize i = 0; i < field_count; i++) { reordered_fields[i]->Variable.field_index = i; @@ -5312,7 +5320,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t break; // NOTE(bill): No need to init } { // Checker values - Type *field_types[2] = {t_type_info_ptr, t_rawptr}; + Type *field_types[2] = {t_rawptr, t_type_info_ptr}; isize field_count = 2; if (cl->elems.e[0]->kind == AstNode_FieldValue) { bool fields_visited[2] = {0}; @@ -2080,15 +2080,15 @@ irValue *ir_emit_comp(irProcedure *proc, TokenKind op_kind, irValue *left, irVal irValue *ir_emit_comp_against_nil(irProcedure *proc, TokenKind op_kind, irValue *x) { Type *t = ir_type(x); if (is_type_any(t)) { - irValue *ti = ir_emit_struct_ev(proc, x, 0); - irValue *data = ir_emit_struct_ev(proc, x, 1); + irValue *data = ir_emit_struct_ev(proc, x, 0); + irValue *ti = ir_emit_struct_ev(proc, x, 1); if (op_kind == Token_CmpEq) { - irValue *a = ir_emit_comp(proc, Token_CmpEq, ti, v_raw_nil); - irValue *b = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil); + irValue *a = ir_emit_comp(proc, Token_CmpEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_CmpEq, ti, v_raw_nil); return ir_emit_arith(proc, Token_Or, a, b, t_bool); } else if (op_kind == Token_NotEq) { - irValue *a = ir_emit_comp(proc, Token_NotEq, ti, v_raw_nil); - irValue *b = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil); + irValue *a = ir_emit_comp(proc, Token_NotEq, data, v_raw_nil); + irValue *b = ir_emit_comp(proc, Token_NotEq, ti, v_raw_nil); return ir_emit_arith(proc, Token_And, a, b, t_bool); } } else if (is_type_slice(t)) { @@ -2249,8 +2249,8 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { } } else if (is_type_any(t)) { switch (index) { - case 0: result_type = make_type_pointer(a, t_type_info_ptr); break; - case 1: result_type = make_type_pointer(a, t_rawptr); break; + case 0: result_type = make_type_pointer(a, t_rawptr); break; + case 1: result_type = make_type_pointer(a, t_type_info_ptr); break; } } else if (is_type_dynamic_array(t)) { switch (index) { @@ -2322,8 +2322,8 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { } } else if (is_type_any(t)) { switch (index) { - case 0: result_type = t_type_info_ptr; break; - case 1: result_type = t_rawptr; break; + case 0: result_type = t_rawptr; break; + case 1: result_type = t_type_info_ptr; break; } } else if (is_type_dynamic_array(t)) { switch (index) { @@ -2375,9 +2375,9 @@ irValue *ir_emit_deep_field_gep(irProcedure *proc, irValue *e, Selection sel) { switch (type->Basic.kind) { case Basic_any: { if (index == 0) { - type = t_type_info_ptr; - } else if (index == 1) { type = t_rawptr; + } else if (index == 1) { + type = t_type_info_ptr; } e = ir_emit_struct_ep(proc, e, index); } break; @@ -2881,10 +2881,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { irValue *ti = ir_type_info(proc, st); - irValue *gep0 = ir_emit_struct_ep(proc, result, 0); - irValue *gep1 = ir_emit_struct_ep(proc, result, 1); - ir_emit_store(proc, gep0, ti); - ir_emit_store(proc, gep1, data); + ir_emit_store(proc, ir_emit_struct_ep(proc, result, 0), data); + ir_emit_store(proc, ir_emit_struct_ep(proc, result, 1), ti); return ir_emit_load(proc, result); } @@ -5217,12 +5215,12 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) { if (cl->elems.count > 0) { ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr))); String field_names[2] = { - str_lit("type_info"), str_lit("data"), + str_lit("type_info"), }; Type *field_types[2] = { - t_type_info_ptr, t_rawptr, + t_type_info_ptr, }; for_array(field_index, cl->elems) { @@ -6322,7 +6320,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { GB_ASSERT(index != NULL); cond = ir_emit_comp(proc, Token_CmpEq, tag_index, index); } else if (match_type_kind == MatchType_Any) { - irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 0)); + irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1)); irValue *case_ti = ir_type_info(proc, case_type); cond = ir_emit_comp(proc, Token_CmpEq, any_ti, case_ti); } @@ -6356,7 +6354,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) { if (match_type_kind == MatchType_Union) { data = union_data; } else if (match_type_kind == MatchType_Any) { - irValue *any_data = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1)); + irValue *any_data = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 0)); data = any_data; } value = ir_emit_conv(proc, data, ct); diff --git a/src/ir_print.c b/src/ir_print.c index 7931c476f..2b5cc909b 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -1596,9 +1596,9 @@ void print_llvm_ir(irGen *ir) { ir_print_encoded_local(f, str_lit("..any")); ir_fprintf(f, " = type {"); - ir_print_type(f, m, t_type_info_ptr); - ir_fprintf(f, ", "); ir_print_type(f, m, t_rawptr); + ir_fprintf(f, ", "); + ir_print_type(f, m, t_type_info_ptr); ir_fprintf(f, "} ; Basic_any\n"); ir_fprintf(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n"); diff --git a/src/parser.c b/src/parser.c index 687902395..277d4069c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -3312,6 +3312,7 @@ AstNode *parse_stmt(AstFile *f) { expect_semicolon(f, decl); if (decl->kind == AstNode_ValueDecl) { + #if 1 if (!decl->ValueDecl.is_var) { syntax_error(token, "`using` may not be applied to constant declarations"); return decl; @@ -3321,6 +3322,9 @@ AstNode *parse_stmt(AstFile *f) { } else { decl->ValueDecl.flags |= VarDeclFlag_using; } + #else + decl->ValueDecl.flags |= VarDeclFlag_using; + #endif return decl; } diff --git a/src/types.c b/src/types.c index fc850c2bc..2f2bbbfef 100644 --- a/src/types.c +++ b/src/types.c @@ -1165,8 +1165,6 @@ ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) { -gb_global Entity *entity__any_type_info = NULL; -gb_global Entity *entity__any_data = NULL; Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel); @@ -1219,6 +1217,10 @@ Selection lookup_field_from_index(gbAllocator a, Type *type, i64 index) { return empty_selection; } + +gb_global Entity *entity__any_data = NULL; +gb_global Entity *entity__any_type_info = NULL; + Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_name, bool is_type, Selection sel) { GB_ASSERT(type_ != NULL); @@ -1238,22 +1240,22 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n #if 1 // IMPORTANT TODO(bill): Should these members be available to should I only allow them with // `Raw_Any` type? - String type_info_str = str_lit("type_info"); String data_str = str_lit("data"); - if (entity__any_type_info == NULL) { - entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 0); - } + String type_info_str = str_lit("type_info"); if (entity__any_data == NULL) { - entity__any_data = make_entity_field(a, NULL, make_token_ident(data_str), t_rawptr, false, 1); + entity__any_data = make_entity_field(a, NULL, make_token_ident(data_str), t_rawptr, false, 0); + } + if (entity__any_type_info == NULL) { + entity__any_type_info = make_entity_field(a, NULL, make_token_ident(type_info_str), t_type_info_ptr, false, 1); } - if (str_eq(field_name, type_info_str)) { + if (str_eq(field_name, data_str)) { selection_add_index(&sel, 0); - sel.entity = entity__any_type_info; + sel.entity = entity__any_data;; return sel; - } else if (str_eq(field_name, data_str)) { + } else if (str_eq(field_name, type_info_str)) { selection_add_index(&sel, 1); - sel.entity = entity__any_data; + sel.entity = entity__any_type_info; return sel; } #endif |