mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-23 22:25:00 -07:00
Swap memory layout of any
This commit is contained in:
+2
-2
@@ -29,6 +29,7 @@ Type_Info_Record :: struct #ordered {
|
||||
types: []^Type_Info,
|
||||
names: []string,
|
||||
offsets: []int, // offsets may not be used in tuples
|
||||
usings: []bool, // usings may not be used in tuples
|
||||
packed: bool,
|
||||
ordered: bool,
|
||||
custom_align: bool,
|
||||
@@ -147,6 +148,7 @@ Allocator :: struct #ordered {
|
||||
data: rawptr,
|
||||
}
|
||||
|
||||
|
||||
Context :: struct #ordered {
|
||||
thread_id: int,
|
||||
|
||||
@@ -277,8 +279,6 @@ default_allocator :: proc() -> Allocator {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
__string_eq :: proc(a, b: string) -> bool {
|
||||
if len(a) != len(b) {
|
||||
return false;
|
||||
|
||||
+12
-12
@@ -669,12 +669,12 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
case Enum:
|
||||
match verb {
|
||||
case 'd', 'f':
|
||||
fmt_arg(fi, any{type_info_base(e.base), v.data}, verb);
|
||||
fmt_arg(fi, any{v.data, type_info_base(e.base)}, verb);
|
||||
case 's', 'v':
|
||||
i: i64;
|
||||
f: f64;
|
||||
ok := false;
|
||||
a := any{type_info_base(e.base), v.data};
|
||||
a := any{v.data, type_info_base(e.base)};
|
||||
match v in a {
|
||||
case i8: i = cast(i64)v;
|
||||
case i16: i = cast(i64)v;
|
||||
@@ -746,12 +746,12 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, b.names[i]);
|
||||
write_string(fi.buf, " = ");
|
||||
data := cast(^byte)v.data + b.offsets[i];
|
||||
fmt_arg(fi, any{b.types[i], cast(rawptr)data}, 'v');
|
||||
fmt_arg(fi, any{cast(rawptr)data, b.types[i]}, 'v');
|
||||
}
|
||||
write_byte(fi.buf, '}');
|
||||
|
||||
default:
|
||||
fmt_value(fi, any{info.base, v.data}, verb);
|
||||
fmt_value(fi, any{v.data, info.base}, verb);
|
||||
}
|
||||
|
||||
case Boolean: fmt_arg(fi, v, verb);
|
||||
@@ -781,7 +781,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
data := cast(^byte)v.data + i*info.elem_size;
|
||||
fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v');
|
||||
fmt_arg(fi, any{cast(rawptr)data, info.elem}, 'v');
|
||||
}
|
||||
|
||||
case Dynamic_Array:
|
||||
@@ -798,7 +798,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
data := cast(^byte)array.data + i*info.elem_size;
|
||||
fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v');
|
||||
fmt_arg(fi, any{cast(rawptr)data, info.elem}, 'v');
|
||||
}
|
||||
|
||||
case Map:
|
||||
@@ -826,13 +826,13 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, header.key.str);
|
||||
} else {
|
||||
fi := Fmt_Info{buf = fi.buf};
|
||||
fmt_arg(^fi, any{info.key, cast(rawptr)^header.key.hash}, 'v');
|
||||
fmt_arg(^fi, any{cast(rawptr)^header.key.hash, info.key}, 'v');
|
||||
}
|
||||
|
||||
write_string(fi.buf, "=");
|
||||
|
||||
value := data + entry_type.offsets[2];
|
||||
fmt_arg(fi, any{info.value, cast(rawptr)value}, 'v');
|
||||
fmt_arg(fi, any{cast(rawptr)value, info.value}, 'v');
|
||||
}
|
||||
|
||||
case Slice:
|
||||
@@ -849,7 +849,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
data := ^slice[0] + i*info.elem_size;
|
||||
fmt_arg(fi, any{info.elem, cast(rawptr)data}, 'v');
|
||||
fmt_arg(fi, any{cast(rawptr)data, info.elem}, 'v');
|
||||
}
|
||||
|
||||
case Vector:
|
||||
@@ -862,7 +862,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
}
|
||||
|
||||
data := cast(^byte)v.data + i*info.elem_size;
|
||||
fmt_value(fi, any{info.elem, cast(rawptr)data}, 'v');
|
||||
fmt_value(fi, any{cast(rawptr)data, info.elem}, 'v');
|
||||
}
|
||||
|
||||
case Struct:
|
||||
@@ -876,7 +876,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, info.names[i]);
|
||||
write_string(fi.buf, " = ");
|
||||
data := cast(^byte)v.data + info.offsets[i];
|
||||
fmt_value(fi, any{info.types[i], cast(rawptr)data}, 'v');
|
||||
fmt_value(fi, any{cast(rawptr)data, info.types[i]}, 'v');
|
||||
}
|
||||
|
||||
case Union:
|
||||
@@ -892,7 +892,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
write_string(fi.buf, cf.names[i]);
|
||||
write_string(fi.buf, " = ");
|
||||
data := cast(^byte)v.data + cf.offsets[i];
|
||||
fmt_value(fi, any{cf.types[i], cast(rawptr)data}, 'v');
|
||||
fmt_value(fi, any{cast(rawptr)data, cf.types[i]}, 'v');
|
||||
}
|
||||
|
||||
case Raw_Union:
|
||||
|
||||
+19
-11
@@ -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);
|
||||
|
||||
+2
-2
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+13
-11
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user