From 3195fac92bab087e4b741e08204c00b49caa065b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 12 Sep 2021 16:47:17 +0100 Subject: Fix slice indices endianness --- src/llvm_backend_expr.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 8189aec68..a4b4564c0 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -888,7 +888,6 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { return {}; } - lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { lbModule *m = p->module; t = reduce_tuple_to_single_type(t); @@ -2981,8 +2980,12 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { lbValue low = lb_const_int(p->module, t_int, 0); lbValue high = {}; - if (se->low != nullptr) low = lb_build_expr(p, se->low); - if (se->high != nullptr) high = lb_build_expr(p, se->high); + if (se->low != nullptr) { + low = lb_correct_endianness(p, lb_build_expr(p, se->low)); + } + if (se->high != nullptr) { + high = lb_correct_endianness(p, lb_build_expr(p, se->high)); + } bool no_indices = se->low == nullptr && se->high == nullptr; -- cgit v1.2.3 From fb8fa5217d4a5081dacc0a74a786cd2efc964fdb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 Sep 2021 00:58:39 +0100 Subject: Begin minimize `Type` size by replacing `Array` with `Slice` etc --- src/array.cpp | 13 +++++++++++ src/check_builtin.cpp | 32 +++++++++++++------------- src/check_expr.cpp | 36 +++++++++++++++++++---------- src/check_type.cpp | 55 +++++++++++++++++++++++--------------------- src/checker.cpp | 39 +++++++++++++++++-------------- src/llvm_backend.cpp | 6 ++--- src/llvm_backend_const.cpp | 4 ++-- src/llvm_backend_expr.cpp | 8 +++---- src/llvm_backend_general.cpp | 2 +- src/llvm_backend_proc.cpp | 4 ++-- src/llvm_backend_stmt.cpp | 6 ++--- src/llvm_backend_type.cpp | 4 ++-- src/types.cpp | 48 ++++++++++++++++++++------------------ 13 files changed, 147 insertions(+), 110 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/array.cpp b/src/array.cpp index 90d85563c..521fa91e2 100644 --- a/src/array.cpp +++ b/src/array.cpp @@ -150,6 +150,19 @@ void slice_copy(Slice *slice, Slice const &data, isize offset, isize count +template +gb_inline Slice slice(Slice const &array, isize lo, isize hi) { + GB_ASSERT(0 <= lo && lo <= hi && hi <= array.count); + Slice out = {}; + isize len = hi-lo; + if (len > 0) { + out.data = array.data+lo; + out.count = len; + } + return out; +} + + template void slice_ordered_remove(Slice *array, isize index) { GB_ASSERT(0 <= index && index < array->count); diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 1f3928bd8..1f9eea45d 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -64,13 +64,13 @@ void check_or_else_split_types(CheckerContext *c, Operand *x, String const &name Type *right_type = nullptr; if (x->type->kind == Type_Tuple) { auto const &vars = x->type->Tuple.variables; - auto lhs = array_slice(vars, 0, vars.count-1); + auto lhs = slice(vars, 0, vars.count-1); auto rhs = vars[vars.count-1]; if (lhs.count == 1) { left_type = lhs[0]->type; } else if (lhs.count != 0) { left_type = alloc_type_tuple(); - left_type->Tuple.variables = array_make_from_ptr(lhs.data, lhs.count, lhs.count); + left_type->Tuple.variables = lhs; } right_type = rhs->type; @@ -120,13 +120,13 @@ void check_or_return_split_types(CheckerContext *c, Operand *x, String const &na Type *right_type = nullptr; if (x->type->kind == Type_Tuple) { auto const &vars = x->type->Tuple.variables; - auto lhs = array_slice(vars, 0, vars.count-1); + auto lhs = slice(vars, 0, vars.count-1); auto rhs = vars[vars.count-1]; if (lhs.count == 1) { left_type = lhs[0]->type; } else if (lhs.count != 0) { left_type = alloc_type_tuple(); - left_type->Tuple.variables = array_make_from_ptr(lhs.data, lhs.count, lhs.count); + left_type->Tuple.variables = lhs; } right_type = rhs->type; @@ -1156,12 +1156,12 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 if (is_type_struct(type)) { isize variable_count = type->Struct.fields.count; - array_init(&tuple->Tuple.variables, a, variable_count); + slice_init(&tuple->Tuple.variables, a, variable_count); // TODO(bill): Should I copy each of the entities or is this good enough? gb_memmove_array(tuple->Tuple.variables.data, type->Struct.fields.data, variable_count); } else if (is_type_array(type)) { isize variable_count = cast(isize)type->Array.count; - array_init(&tuple->Tuple.variables, a, variable_count); + slice_init(&tuple->Tuple.variables, a, variable_count); for (isize i = 0; i < variable_count; i++) { tuple->Tuple.variables[i] = alloc_entity_array_elem(nullptr, blank_token, type->Array.elem, cast(i32)i); } @@ -1240,14 +1240,14 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } else if (is_type_enum(type)) { operand->mode = Addressing_Constant; operand->type = original_type; - operand->value = type->Enum.min_value; + operand->value = *type->Enum.min_value; return true; } else if (is_type_enumerated_array(type)) { Type *bt = base_type(type); GB_ASSERT(bt->kind == Type_EnumeratedArray); operand->mode = Addressing_Constant; operand->type = bt->EnumeratedArray.index; - operand->value = bt->EnumeratedArray.min_value; + operand->value = *bt->EnumeratedArray.min_value; return true; } gbString type_str = type_to_string(original_type); @@ -1414,14 +1414,14 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } else if (is_type_enum(type)) { operand->mode = Addressing_Constant; operand->type = original_type; - operand->value = type->Enum.max_value; + operand->value = *type->Enum.max_value; return true; } else if (is_type_enumerated_array(type)) { Type *bt = base_type(type); GB_ASSERT(bt->kind == Type_EnumeratedArray); operand->mode = Addressing_Constant; operand->type = bt->EnumeratedArray.index; - operand->value = bt->EnumeratedArray.max_value; + operand->value = *bt->EnumeratedArray.max_value; return true; } gbString type_str = type_to_string(original_type); @@ -1788,8 +1788,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 if (elem == nullptr) { elem = alloc_type_struct(); elem->Struct.scope = s; - elem->Struct.fields = fields; - elem->Struct.tags = array_make(permanent_allocator(), fields.count); + elem->Struct.fields = slice_from_array(fields); + elem->Struct.tags = slice_make(permanent_allocator(), fields.count); elem->Struct.node = dummy_node_struct; type_set_offsets(elem); } @@ -1938,8 +1938,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 if (is_type_array(elem)) { Type *old_array = base_type(elem); soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), cast(isize)old_array->Array.count); - soa_struct->Struct.tags = array_make(heap_allocator(), cast(isize)old_array->Array.count); + soa_struct->Struct.fields = slice_make(heap_allocator(), cast(isize)old_array->Array.count); + soa_struct->Struct.tags = slice_make(heap_allocator(), cast(isize)old_array->Array.count); soa_struct->Struct.node = operand->expr; soa_struct->Struct.soa_kind = StructSoa_Fixed; soa_struct->Struct.soa_elem = elem; @@ -1971,8 +1971,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 Type *old_struct = base_type(elem); soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), old_struct->Struct.fields.count); - soa_struct->Struct.tags = array_make(heap_allocator(), old_struct->Struct.tags.count); + soa_struct->Struct.fields = slice_make(heap_allocator(), old_struct->Struct.fields.count); + soa_struct->Struct.tags = slice_make(heap_allocator(), old_struct->Struct.tags.count); soa_struct->Struct.node = operand->expr; soa_struct->Struct.soa_kind = StructSoa_Fixed; soa_struct->Struct.soa_elem = elem; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8607ee3cb..69d60d651 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -1023,10 +1023,10 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, if (poly->EnumeratedArray.count != source->EnumeratedArray.count) { return false; } - if (compare_exact_values(Token_NotEq, poly->EnumeratedArray.min_value, source->EnumeratedArray.min_value)) { + if (compare_exact_values(Token_NotEq, *poly->EnumeratedArray.min_value, *source->EnumeratedArray.min_value)) { return false; } - if (compare_exact_values(Token_NotEq, poly->EnumeratedArray.max_value, source->EnumeratedArray.max_value)) { + if (compare_exact_values(Token_NotEq, *poly->EnumeratedArray.max_value, *source->EnumeratedArray.max_value)) { return false; } return is_polymorphic_type_assignable(c, poly->EnumeratedArray.index, source->EnumeratedArray.index, true, modify_type); @@ -3425,8 +3425,8 @@ bool check_index_value(CheckerContext *c, Type *main_type, bool open_range, Ast if (is_type_enum(index_type)) { Type *bt = base_type(index_type); GB_ASSERT(bt->kind == Type_Enum); - ExactValue lo = bt->Enum.min_value; - ExactValue hi = bt->Enum.max_value; + ExactValue const &lo = *bt->Enum.min_value; + ExactValue const &hi = *bt->Enum.max_value; String lo_str = {}; String hi_str = {}; if (bt->Enum.fields.count > 0) { @@ -3556,7 +3556,7 @@ ExactValue get_constant_field_single(CheckerContext *c, ExactValue value, i32 in if (is_type_enumerated_array(node->tav.type)) { Type *bt = base_type(node->tav.type); GB_ASSERT(bt->kind == Type_EnumeratedArray); - corrected_index = index + exact_value_to_i64(bt->EnumeratedArray.min_value); + corrected_index = index + exact_value_to_i64(*bt->EnumeratedArray.min_value); } if (op != Token_RangeHalf) { if (lo <= corrected_index && corrected_index <= hi) { @@ -3580,7 +3580,7 @@ ExactValue get_constant_field_single(CheckerContext *c, ExactValue value, i32 in if (is_type_enumerated_array(node->tav.type)) { Type *bt = base_type(node->tav.type); GB_ASSERT(bt->kind == Type_EnumeratedArray); - index_value = exact_value_sub(index_value, bt->EnumeratedArray.min_value); + index_value = exact_value_sub(index_value, *bt->EnumeratedArray.min_value); } i64 field_index = exact_value_to_i64(index_value); @@ -3738,6 +3738,18 @@ void check_did_you_mean_type(String const &name, Array const &fields) check_did_you_mean_print(&d); } +void check_did_you_mean_type(String const &name, Slice const &fields) { + ERROR_BLOCK(); + + DidYouMeanAnswers d = did_you_mean_make(heap_allocator(), fields.count, name); + defer (did_you_mean_destroy(&d)); + + for_array(i, fields) { + did_you_mean_append(&d, fields[i]->token.string); + } + check_did_you_mean_print(&d); +} + void check_did_you_mean_scope(String const &name, Scope *scope) { ERROR_BLOCK(); @@ -7305,8 +7317,8 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type gbString index_type_str = type_to_string(index_type); defer (gb_string_free(index_type_str)); - i64 total_lo = exact_value_to_i64(t->EnumeratedArray.min_value); - i64 total_hi = exact_value_to_i64(t->EnumeratedArray.max_value); + i64 total_lo = exact_value_to_i64(*t->EnumeratedArray.min_value); + i64 total_hi = exact_value_to_i64(*t->EnumeratedArray.max_value); String total_lo_string = {}; String total_hi_string = {}; @@ -7319,10 +7331,10 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type if (f->kind != Entity_Constant) { continue; } - if (total_lo_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, t->EnumeratedArray.min_value)) { + if (total_lo_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.min_value)) { total_lo_string = f->token.string; } - if (total_hi_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, t->EnumeratedArray.max_value)) { + if (total_hi_string.len == 0 && compare_exact_values(Token_CmpEq, f->Constant.value, *t->EnumeratedArray.max_value)) { total_hi_string = f->token.string; } if (total_lo_string.len != 0 && total_hi_string.len != 0) { @@ -8472,13 +8484,13 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type Type *params = alloc_type_tuple(); Type *results = alloc_type_tuple(); if (param_types.count != 0) { - array_init(¶ms->Tuple.variables, heap_allocator(), param_types.count); + slice_init(¶ms->Tuple.variables, heap_allocator(), param_types.count); for_array(i, param_types) { params->Tuple.variables[i] = alloc_entity_param(scope, blank_token, param_types[i], false, true); } } if (return_type != nullptr) { - array_init(&results->Tuple.variables, heap_allocator(), 1); + slice_init(&results->Tuple.variables, heap_allocator(), 1); results->Tuple.variables[0] = alloc_entity_param(scope, blank_token, return_type, false, true); } diff --git a/src/check_type.cpp b/src/check_type.cpp index 3541eef61..2c9f589c7 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -92,10 +92,10 @@ bool does_field_type_allow_using(Type *t) { return false; } -void check_struct_fields(CheckerContext *ctx, Ast *node, Array *fields, Array *tags, Slice const ¶ms, +void check_struct_fields(CheckerContext *ctx, Ast *node, Slice *fields, Slice *tags, Slice const ¶ms, isize init_field_capacity, Type *struct_type, String context) { - *fields = array_make(heap_allocator(), 0, init_field_capacity); - *tags = array_make(heap_allocator(), 0, init_field_capacity); + auto fields_array = array_make(heap_allocator(), 0, init_field_capacity); + auto tags_array = array_make(heap_allocator(), 0, init_field_capacity); GB_ASSERT(node->kind == Ast_StructType); GB_ASSERT(struct_type->kind == Type_Struct); @@ -153,20 +153,20 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array *fields Entity *field = alloc_entity_field(ctx->scope, name_token, type, is_using, field_src_index); add_entity(ctx, ctx->scope, name, field); - array_add(fields, field); + array_add(&fields_array, field); String tag = p->tag.string; if (tag.len != 0 && !unquote_string(permanent_allocator(), &tag, 0, tag.text[0] == '`')) { error(p->tag, "Invalid string literal"); tag = {}; } - array_add(tags, tag); + array_add(&tags_array, tag); field_src_index += 1; } if (is_using && p->names.count > 0) { - Type *first_type = (*fields)[fields->count-1]->type; + Type *first_type = fields_array[fields_array.count-1]->type; Type *t = base_type(type_deref(first_type)); if (!does_field_type_allow_using(t) && @@ -182,6 +182,9 @@ void check_struct_fields(CheckerContext *ctx, Ast *node, Array *fields populate_using_entity_scope(ctx, node, p, type); } } + + *fields = slice_from_array(fields_array); + *tags = slice_from_array(tags_array); } @@ -498,7 +501,7 @@ Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *polymorphic_para if (entities.count > 0) { Type *tuple = alloc_type_tuple(); - tuple->Tuple.variables = entities; + tuple->Tuple.variables = slice_from_array(entities); polymorphic_params_type = tuple; } } @@ -816,8 +819,8 @@ void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *named_type, Ast enum_type->Enum.fields = fields; enum_type->Enum.names = make_names_field_for_struct(ctx, ctx->scope); - enum_type->Enum.min_value = min_value; - enum_type->Enum.max_value = max_value; + *enum_type->Enum.min_value = min_value; + *enum_type->Enum.max_value = max_value; enum_type->Enum.min_value_index = min_value_index; enum_type->Enum.max_value_index = max_value_index; @@ -1705,7 +1708,7 @@ Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_params, bool *is } Type *tuple = alloc_type_tuple(); - tuple->Tuple.variables = variables; + tuple->Tuple.variables = slice_from_array(variables); if (success_) *success_ = success; if (specialization_count_) *specialization_count_ = specialization_count; @@ -1815,7 +1818,7 @@ Type *check_get_results(CheckerContext *ctx, Scope *scope, Ast *_results) { } } - tuple->Tuple.variables = variables; + tuple->Tuple.variables = slice_from_array(variables); return tuple; } @@ -2059,7 +2062,7 @@ i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) { Type *make_optional_ok_type(Type *value, bool typed) { gbAllocator a = permanent_allocator(); Type *t = alloc_type_tuple(); - array_init(&t->Tuple.variables, a, 2); + slice_init(&t->Tuple.variables, a, 2); t->Tuple.variables[0] = alloc_entity_field(nullptr, blank_token, value, false, 0); t->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, typed ? t_bool : t_untyped_bool, false, 1); return t; @@ -2083,11 +2086,11 @@ void init_map_entry_type(Type *type) { */ Scope *s = create_scope(nullptr, builtin_pkg->scope); - auto fields = array_make(permanent_allocator(), 0, 4); - array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("hash")), t_uintptr, false, cast(i32)fields.count, EntityState_Resolved)); - array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, cast(i32)fields.count, EntityState_Resolved)); - array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("key")), type->Map.key, false, cast(i32)fields.count, EntityState_Resolved)); - array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, cast(i32)fields.count, EntityState_Resolved)); + auto fields = slice_make(permanent_allocator(), 4); + fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hash")), t_uintptr, false, cast(i32)fields.count, EntityState_Resolved); + fields[1] = alloc_entity_field(s, make_token_ident(str_lit("next")), t_int, false, cast(i32)fields.count, EntityState_Resolved); + fields[2] = alloc_entity_field(s, make_token_ident(str_lit("key")), type->Map.key, false, cast(i32)fields.count, EntityState_Resolved); + fields[3] = alloc_entity_field(s, make_token_ident(str_lit("value")), type->Map.value, false, cast(i32)fields.count, EntityState_Resolved); entry_type->Struct.fields = fields; @@ -2120,9 +2123,9 @@ void init_map_internal_types(Type *type) { Type *entries_type = alloc_type_dynamic_array(type->Map.entry_type); - auto fields = array_make(permanent_allocator(), 0, 2); - array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved)); - array_add(&fields, alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved)); + auto fields = slice_make(permanent_allocator(), 2); + fields[0] = alloc_entity_field(s, make_token_ident(str_lit("hashes")), hashes_type, false, 0, EntityState_Resolved); + fields[1] = alloc_entity_field(s, make_token_ident(str_lit("entries")), entries_type, false, 1, EntityState_Resolved); generated_struct_type->Struct.fields = fields; @@ -2239,8 +2242,8 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el field_count = 0; soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+extra_field_count); - soa_struct->Struct.tags = array_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.fields = slice_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.tags = slice_make(heap_allocator(), field_count+extra_field_count); soa_struct->Struct.node = array_typ_expr; soa_struct->Struct.soa_kind = soa_kind; soa_struct->Struct.soa_elem = elem; @@ -2254,8 +2257,8 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el field_count = cast(isize)old_array->Array.count; soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+extra_field_count); - soa_struct->Struct.tags = array_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.fields = slice_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.tags = slice_make(heap_allocator(), field_count+extra_field_count); soa_struct->Struct.node = array_typ_expr; soa_struct->Struct.soa_kind = soa_kind; soa_struct->Struct.soa_elem = elem; @@ -2296,8 +2299,8 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el GB_ASSERT(old_struct->Struct.tags.count == field_count); soa_struct = alloc_type_struct(); - soa_struct->Struct.fields = array_make(heap_allocator(), field_count+extra_field_count); - soa_struct->Struct.tags = array_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.fields = slice_make(heap_allocator(), field_count+extra_field_count); + soa_struct->Struct.tags = slice_make(heap_allocator(), field_count+extra_field_count); soa_struct->Struct.node = array_typ_expr; soa_struct->Struct.soa_kind = soa_kind; soa_struct->Struct.soa_elem = elem; diff --git a/src/checker.cpp b/src/checker.cpp index 5544ef58e..8d85784fa 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -4865,22 +4865,25 @@ void check_deferred_procedures(Checker *c) { Entity *dst = src->Procedure.deferred_procedure.entity; GB_ASSERT(dst != nullptr); GB_ASSERT(dst->kind == Entity_Procedure); + + char const *attribute = "deferred_none"; + switch (dst_kind) { + case DeferredProcedure_none: + attribute = "deferred_none"; + break; + case DeferredProcedure_in: + attribute = "deferred_in"; + break; + case DeferredProcedure_out: + attribute = "deferred_out"; + break; + case DeferredProcedure_in_out: + attribute = "deferred_in_out"; + break; + } if (is_type_polymorphic(src->type) || is_type_polymorphic(dst->type)) { - switch (dst_kind) { - case DeferredProcedure_none: - error(src->token, "'deferred_none' cannot be used with a polymorphic procedure"); - break; - case DeferredProcedure_in: - error(src->token, "'deferred_in' cannot be used with a polymorphic procedure"); - break; - case DeferredProcedure_out: - error(src->token, "'deferred_out' cannot be used with a polymorphic procedure"); - break; - case DeferredProcedure_in_out: - error(src->token, "'deferred_in_out' cannot be used with a polymorphic procedure"); - break; - } + error(src->token, "'%s' cannot be used with a polymorphic procedure", attribute); continue; } @@ -4974,17 +4977,19 @@ void check_deferred_procedures(Checker *c) { GB_ASSERT(src_results->kind == Type_Tuple); len += src_results->Tuple.variables.count; } - array_init(&sv, heap_allocator(), 0, len); + slice_init(&sv, heap_allocator(), len); + isize offset = 0; if (src_params != nullptr) { for_array(i, src_params->Tuple.variables) { - array_add(&sv, src_params->Tuple.variables[i]); + sv[offset++] = src_params->Tuple.variables[i]; } } if (src_results != nullptr) { for_array(i, src_results->Tuple.variables) { - array_add(&sv, src_results->Tuple.variables[i]); + sv[offset++] = src_results->Tuple.variables[i]; } } + GB_ASSERT(offset == len); if (are_types_identical(tsrc, dst_params)) { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 5fff3c486..3e8498776 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -761,7 +761,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) if (build_context.metrics.os == TargetOs_windows && build_context.build_mode == BuildMode_DynamicLibrary) { is_dll_main = true; name = str_lit("DllMain"); - array_init(¶ms->Tuple.variables, permanent_allocator(), 3); + slice_init(¶ms->Tuple.variables, permanent_allocator(), 3); params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("hinstDLL"), t_rawptr, false, true); params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("fdwReason"), t_u32, false, true); params->Tuple.variables[2] = alloc_entity_param(nullptr, make_token_ident("lpReserved"), t_rawptr, false, true); @@ -769,12 +769,12 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) name = str_lit("mainCRTStartup"); } else { has_args = true; - array_init(¶ms->Tuple.variables, permanent_allocator(), 2); + slice_init(¶ms->Tuple.variables, permanent_allocator(), 2); params->Tuple.variables[0] = alloc_entity_param(nullptr, make_token_ident("argc"), t_i32, false, true); params->Tuple.variables[1] = alloc_entity_param(nullptr, make_token_ident("argv"), t_ptr_cstring, false, true); } - array_init(&results->Tuple.variables, permanent_allocator(), 1); + slice_init(&results->Tuple.variables, permanent_allocator(), 1); results->Tuple.variables[0] = alloc_entity_param(nullptr, blank_token, t_i32, false, true); Type *proc_type = alloc_type_proc(nullptr, diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 5ad2b09b6..d46992976 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -690,8 +690,8 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc isize value_index = 0; - i64 total_lo = exact_value_to_i64(type->EnumeratedArray.min_value); - i64 total_hi = exact_value_to_i64(type->EnumeratedArray.max_value); + i64 total_lo = exact_value_to_i64(*type->EnumeratedArray.min_value); + i64 total_hi = exact_value_to_i64(*type->EnumeratedArray.max_value); for (i64 i = total_lo; i <= total_hi; i++) { bool found = false; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index a4b4564c0..efd0eaf40 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2872,13 +2872,13 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { auto index_tv = type_and_value_of_expr(ie->index); lbValue index = {}; - if (compare_exact_values(Token_NotEq, t->EnumeratedArray.min_value, exact_value_i64(0))) { + if (compare_exact_values(Token_NotEq, *t->EnumeratedArray.min_value, exact_value_i64(0))) { if (index_tv.mode == Addressing_Constant) { - ExactValue idx = exact_value_sub(index_tv.value, t->EnumeratedArray.min_value); + ExactValue idx = exact_value_sub(index_tv.value, *t->EnumeratedArray.min_value); index = lb_const_value(p->module, index_type, idx); } else { index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int); - index = lb_emit_arith(p, Token_Sub, index, lb_const_value(p->module, index_type, t->EnumeratedArray.min_value), index_type); + index = lb_emit_arith(p, Token_Sub, index, lb_const_value(p->module, index_type, *t->EnumeratedArray.min_value), index_type); } } else { index = lb_emit_conv(p, lb_build_expr(p, ie->index), t_int); @@ -3472,7 +3472,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { } - i32 index_offset = cast(i32)exact_value_to_i64(bt->EnumeratedArray.min_value); + i32 index_offset = cast(i32)exact_value_to_i64(*bt->EnumeratedArray.min_value); for_array(i, temp_data) { i32 index = temp_data[i].elem_index - index_offset; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 113c9ba62..f481c122e 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1670,7 +1670,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef *fields = gb_alloc_array(permanent_allocator(), LLVMTypeRef, field_count); i64 alignment = type_align_of(type); unsigned size_of_union = cast(unsigned)type_size_of(type); - fields[0] = lb_alignment_prefix_type_hack(m, alignment); + fields[0] = lb_alignment_prefix_type_hack(m, gb_min(alignment, 16)); fields[1] = LLVMArrayType(lb_type(m, t_u8), size_of_union); return LLVMStructTypeInContext(ctx, fields, field_count, false); } diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index ffbb532f0..ce6807571 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1393,7 +1393,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, Type *res_type = nullptr; gbAllocator a = permanent_allocator(); res_type = alloc_type_tuple(); - array_init(&res_type->Tuple.variables, a, 2); + slice_init(&res_type->Tuple.variables, a, 2); res_type->Tuple.variables[0] = alloc_entity_field(nullptr, blank_token, type, false, 0); res_type->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, t_llvm_bool, false, 1); @@ -1738,7 +1738,7 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv, if (tv.type->kind == Type_Tuple) { Type *fix_typed = alloc_type_tuple(); - array_init(&fix_typed->Tuple.variables, permanent_allocator(), 2); + slice_init(&fix_typed->Tuple.variables, permanent_allocator(), 2); fix_typed->Tuple.variables[0] = tv.type->Tuple.variables[0]; fix_typed->Tuple.variables[1] = alloc_entity_field(nullptr, blank_token, t_llvm_bool, false, 1); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 148790ac6..ac922b642 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -332,8 +332,8 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu val = lb_emit_load(p, lb_emit_array_ep(p, expr, idx)); // NOTE(bill): Override the idx value for the enumeration Type *index_type = expr_type->EnumeratedArray.index; - if (compare_exact_values(Token_NotEq, expr_type->EnumeratedArray.min_value, exact_value_u64(0))) { - idx = lb_emit_arith(p, Token_Add, idx, lb_const_value(m, index_type, expr_type->EnumeratedArray.min_value), index_type); + if (compare_exact_values(Token_NotEq, *expr_type->EnumeratedArray.min_value, exact_value_u64(0))) { + idx = lb_emit_arith(p, Token_Add, idx, lb_const_value(m, index_type, *expr_type->EnumeratedArray.min_value), index_type); } } break; @@ -984,7 +984,7 @@ void lb_build_unroll_range_stmt(lbProcedure *p, AstUnrollRangeStmt *rs, Scope *s lb_addr_store(p, val0_addr, lb_emit_load(p, elem)); } if (val1_type) { - ExactValue idx = exact_value_add(exact_value_i64(i), t->EnumeratedArray.min_value); + ExactValue idx = exact_value_add(exact_value_i64(i), *t->EnumeratedArray.min_value); lb_addr_store(p, val1_addr, lb_const_value(m, val1_type, idx)); } diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index af3fadc3c..f5665c718 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -450,8 +450,8 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue min_value = lb_emit_struct_ep(p, tag, 4); lbValue max_value = lb_emit_struct_ep(p, tag, 5); - lbValue min_v = lb_const_value(m, t_i64, t->EnumeratedArray.min_value); - lbValue max_v = lb_const_value(m, t_i64, t->EnumeratedArray.max_value); + lbValue min_v = lb_const_value(m, t_i64, *t->EnumeratedArray.min_value); + lbValue max_v = lb_const_value(m, t_i64, *t->EnumeratedArray.max_value); lb_emit_store(p, min_value, min_v); lb_emit_store(p, max_value, max_v); diff --git a/src/types.cpp b/src/types.cpp index 37a05d5a6..4362ae45b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -129,9 +129,9 @@ enum StructSoaKind { }; struct TypeStruct { - Array fields; - Array tags; - Array offsets; + Slice fields; + Slice tags; + Slice offsets; Ast * node; Scope * scope; @@ -145,12 +145,12 @@ struct TypeStruct { i64 soa_count; StructSoaKind soa_kind; - bool are_offsets_set; - bool are_offsets_being_processed; - bool is_packed; - bool is_raw_union; bool is_polymorphic; - bool is_poly_specialized; + bool are_offsets_set : 1; + bool are_offsets_being_processed : 1; + bool is_packed : 1; + bool is_raw_union : 1; + bool is_poly_specialized : 1; }; struct TypeUnion { @@ -216,8 +216,8 @@ struct TypeProc { TYPE_KIND(EnumeratedArray, struct { \ Type *elem; \ Type *index; \ - ExactValue min_value; \ - ExactValue max_value; \ + ExactValue *min_value; \ + ExactValue *max_value; \ i64 count; \ TokenKind op; \ }) \ @@ -239,14 +239,14 @@ struct TypeProc { Scope * scope; \ Entity * names; \ Type * base_type; \ - ExactValue min_value; \ - ExactValue max_value; \ + ExactValue *min_value; \ + ExactValue *max_value; \ isize min_value_index; \ isize max_value_index; \ }) \ TYPE_KIND(Tuple, struct { \ - Array variables; /* Entity_Variable */ \ - Array offsets; \ + Slice variables; /* Entity_Variable */ \ + Slice offsets; \ bool are_offsets_being_processed; \ bool are_offsets_set; \ bool is_packed; \ @@ -803,15 +803,17 @@ Type *alloc_type_array(Type *elem, i64 count, Type *generic_count = nullptr) { return t; } -Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValue min_value, ExactValue max_value, TokenKind op) { +Type *alloc_type_enumerated_array(Type *elem, Type *index, ExactValue const *min_value, ExactValue const *max_value, TokenKind op) { Type *t = alloc_type(Type_EnumeratedArray); t->EnumeratedArray.elem = elem; t->EnumeratedArray.index = index; - t->EnumeratedArray.min_value = min_value; - t->EnumeratedArray.max_value = max_value; + t->EnumeratedArray.min_value = gb_alloc_item(permanent_allocator(), ExactValue); + t->EnumeratedArray.max_value = gb_alloc_item(permanent_allocator(), ExactValue); + gb_memmove(t->EnumeratedArray.min_value, min_value, gb_size_of(ExactValue)); + gb_memmove(t->EnumeratedArray.max_value, max_value, gb_size_of(ExactValue)); t->EnumeratedArray.op = op; - t->EnumeratedArray.count = 1 + exact_value_to_i64(exact_value_sub(max_value, min_value)); + t->EnumeratedArray.count = 1 + exact_value_to_i64(exact_value_sub(*max_value, *min_value)); return t; } @@ -841,6 +843,8 @@ Type *alloc_type_union() { Type *alloc_type_enum() { Type *t = alloc_type(Type_Enum); + t->Enum.min_value = gb_alloc_item(permanent_allocator(), ExactValue); + t->Enum.max_value = gb_alloc_item(permanent_allocator(), ExactValue); return t; } @@ -3080,9 +3084,9 @@ i64 type_align_of_internal(Type *t, TypePath *path) { return gb_clamp(next_pow2(type_size_of_internal(t, path)), 1, build_context.word_size); } -Array type_set_offsets_of(Array const &fields, bool is_packed, bool is_raw_union) { +Slice type_set_offsets_of(Slice const &fields, bool is_packed, bool is_raw_union) { gbAllocator a = permanent_allocator(); - auto offsets = array_make(a, fields.count); + auto offsets = slice_make(a, fields.count); i64 curr_offset = 0; if (is_raw_union) { for_array(i, fields) { @@ -3463,7 +3467,7 @@ Type *reduce_tuple_to_single_type(Type *original_type) { Type *alloc_type_struct_from_field_types(Type **field_types, isize field_count, bool is_packed) { Type *t = alloc_type_struct(); - t->Struct.fields = array_make(heap_allocator(), field_count); + t->Struct.fields = slice_make(heap_allocator(), field_count); Scope *scope = nullptr; for_array(i, t->Struct.fields) { @@ -3483,7 +3487,7 @@ Type *alloc_type_tuple_from_field_types(Type **field_types, isize field_count, b } Type *t = alloc_type_tuple(); - t->Tuple.variables = array_make(heap_allocator(), field_count); + t->Tuple.variables = slice_make(heap_allocator(), field_count); Scope *scope = nullptr; for_array(i, t->Tuple.variables) { -- cgit v1.2.3 From be68bf9f26122b764a43cf61369ca54c203d1df3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 Sep 2021 11:29:46 +0100 Subject: Only store `field_index` remove `field_src_index` (for the time being) --- src/check_builtin.cpp | 2 +- src/check_type.cpp | 2 +- src/entity.cpp | 13 +++++-------- src/llvm_backend_expr.cpp | 2 +- src/llvm_backend_utility.cpp | 20 ++++++++++++-------- src/types.cpp | 2 +- 6 files changed, 21 insertions(+), 20 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 96feb6701..399de98a0 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -1989,7 +1989,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 Entity *old_field = old_struct->Struct.fields[i]; if (old_field->kind == Entity_Variable) { Type *array_type = alloc_type_array(old_field->type, count); - Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_src_index); + Entity *new_field = alloc_entity_field(scope, old_field->token, array_type, false, old_field->Variable.field_index); soa_struct->Struct.fields[i] = new_field; add_entity(c, scope, nullptr, new_field); } else { diff --git a/src/check_type.cpp b/src/check_type.cpp index b80d6c05e..8d129eb68 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2317,7 +2317,7 @@ Type *make_soa_struct_internal(CheckerContext *ctx, Ast *array_typ_expr, Ast *el } else { field_type = alloc_type_pointer(old_field->type); } - Entity *new_field = alloc_entity_field(scope, old_field->token, field_type, false, old_field->Variable.field_src_index); + Entity *new_field = alloc_entity_field(scope, old_field->token, field_type, false, old_field->Variable.field_index); soa_struct->Struct.fields[i] = new_field; add_entity(ctx, scope, nullptr, new_field); add_entity_use(ctx, nullptr, new_field); diff --git a/src/entity.cpp b/src/entity.cpp index 8343ba557..11954113d 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -155,8 +155,7 @@ struct Entity { } Constant; struct { Ast *init_expr; // only used for some variables within procedure bodies - i32 field_index; - i32 field_src_index; + i32 field_index; ParameterValue param_value; Ast * param_expr; @@ -319,20 +318,18 @@ Entity *alloc_entity_const_param(Scope *scope, Token token, Type *type, ExactVal } -Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_src_index, EntityState state = EntityState_Unresolved) { +Entity *alloc_entity_field(Scope *scope, Token token, Type *type, bool is_using, i32 field_index, EntityState state = EntityState_Unresolved) { Entity *entity = alloc_entity_variable(scope, token, type); - entity->Variable.field_src_index = field_src_index; - entity->Variable.field_index = field_src_index; + entity->Variable.field_index = field_index; if (is_using) entity->flags |= EntityFlag_Using; entity->flags |= EntityFlag_Field; entity->state = state; return entity; } -Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_src_index) { +Entity *alloc_entity_array_elem(Scope *scope, Token token, Type *type, i32 field_index) { Entity *entity = alloc_entity_variable(scope, token, type); - entity->Variable.field_src_index = field_src_index; - entity->Variable.field_index = field_src_index; + entity->Variable.field_index = field_index; entity->flags |= EntityFlag_Field; entity->flags |= EntityFlag_ArrayElem; entity->state = EntityState_Resolved; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index efd0eaf40..a34e98f2b 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3259,7 +3259,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { TypeAndValue tav = type_and_value_of_expr(elem); } else { TypeAndValue tav = type_and_value_of_expr(elem); - Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_src_index); + Selection sel = lookup_field_from_index(bt, st->fields[field_index]->Variable.field_index); index = sel.index[0]; } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index db3cb443e..63e27f428 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -807,6 +807,13 @@ lbValue lb_address_from_load(lbProcedure *p, lbValue value) { return {}; } +i32 lb_convert_struct_index(Type *t, i32 index) { + if (t->kind == Type_Struct && t->Struct.custom_align != 0) { + index += 1; + } + return index; +} + lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { GB_ASSERT(is_type_pointer(s.type)); Type *t = base_type(type_deref(s.type)); @@ -883,10 +890,9 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { } GB_ASSERT_MSG(result_type != nullptr, "%s %d", type_to_string(t), index); - - if (t->kind == Type_Struct && t->Struct.custom_align != 0) { - index += 1; - } + + index = lb_convert_struct_index(t, index); + if (lb_is_const(s)) { lbModule *m = p->module; lbValue res = {}; @@ -1006,10 +1012,8 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { } GB_ASSERT_MSG(result_type != nullptr, "%s, %d", type_to_string(s.type), index); - - if (t->kind == Type_Struct && t->Struct.custom_align != 0) { - index += 1; - } + + index = lb_convert_struct_index(t, index); lbValue res = {}; res.value = LLVMBuildExtractValue(p->builder, s.value, cast(unsigned)index, ""); diff --git a/src/types.cpp b/src/types.cpp index 23834bfc1..8eb505287 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -2432,7 +2432,7 @@ Selection lookup_field_from_index(Type *type, i64 index) { for (isize i = 0; i < max_count; i++) { Entity *f = type->Struct.fields[i]; if (f->kind == Entity_Variable) { - if (f->Variable.field_src_index == index) { + if (f->Variable.field_index == index) { auto sel_array = array_make(a, 1); sel_array[0] = cast(i32)i; return make_selection(f, sel_array, false); -- cgit v1.2.3 From 8de728e3dc09eff8840ec3842e731f51865daf03 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 13 Sep 2021 16:40:24 +0100 Subject: LLVM Code Generator: Add explicitly padding between fields in LLVM struct types --- src/llvm_backend.cpp | 4 +- src/llvm_backend.hpp | 3 ++ src/llvm_backend_const.cpp | 84 ++++++++++++++++++++++++++++----------- src/llvm_backend_expr.cpp | 9 ++--- src/llvm_backend_general.cpp | 70 +++++++++++++++++++++++++------- src/llvm_backend_stmt.cpp | 3 +- src/llvm_backend_type.cpp | 95 +++++++++++++++++++++++++++++--------------- src/llvm_backend_utility.cpp | 55 ++++++++++++++++++++++--- 8 files changed, 235 insertions(+), 88 deletions(-) (limited to 'src/llvm_backend_expr.cpp') diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 8ba0a3b87..67160101d 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -806,8 +806,6 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) lbAddr all_tests_array_addr = lb_add_global_generated(p->module, array_type, {}); lbValue all_tests_array = lb_addr_get_ptr(p, all_tests_array_addr); - LLVMTypeRef lbt_Internal_Test = lb_type(m, t_Internal_Test); - LLVMValueRef indices[2] = {}; indices[0] = LLVMConstInt(lb_type(m, t_i32), 0, false); @@ -834,7 +832,7 @@ lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *startup_runtime) GB_ASSERT(LLVMIsConstant(vals[2])); LLVMValueRef dst = LLVMConstInBoundsGEP(all_tests_array.value, indices, gb_count_of(indices)); - LLVMValueRef src = llvm_const_named_struct(lbt_Internal_Test, vals, gb_count_of(vals)); + LLVMValueRef src = llvm_const_named_struct(m, t_Internal_Test, vals, gb_count_of(vals)); LLVMBuildStore(p->builder, src, dst); } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 19e5ffdb6..d0ba29964 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -432,6 +432,7 @@ void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e); lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast *right, Type *type); lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *false_block); +LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_); LLVMValueRef llvm_const_named_struct(LLVMTypeRef t, LLVMValueRef *values, isize value_count_); void lb_set_entity_from_other_modules_linkage_correctly(lbModule *other_module, Entity *e, String const &name); @@ -446,6 +447,8 @@ lbCopyElisionHint lb_set_copy_elision_hint(lbProcedure *p, lbAddr const &addr, A void lb_reset_copy_elision_hint(lbProcedure *p, lbCopyElisionHint prev_hint); lbValue lb_consume_copy_elision_hint(lbProcedure *p); +bool lb_struct_has_padding_prefix(Type *t); + #define LB_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime" #define LB_STARTUP_TYPE_INFO_PROC_NAME "__$startup_type_info" #define LB_TYPE_INFO_DATA_NAME "__$type_info_data" diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index d46992976..cb9369c72 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -99,7 +99,7 @@ LLVMValueRef llvm_const_cast(LLVMValueRef val, LLVMTypeRef dst) { return LLVMConstNull(dst); } - GB_ASSERT(LLVMSizeOf(dst) == LLVMSizeOf(src)); + GB_ASSERT_MSG(LLVMSizeOf(dst) == LLVMSizeOf(src), "%s vs %s", LLVMPrintTypeToString(dst), LLVMPrintTypeToString(src)); LLVMTypeKind kind = LLVMGetTypeKind(dst); switch (kind) { case LLVMPointerTypeKind: @@ -125,11 +125,43 @@ lbValue lb_const_ptr_cast(lbModule *m, lbValue value, Type *t) { return res; } +LLVMValueRef llvm_const_named_struct(lbModule *m, Type *t, LLVMValueRef *values, isize value_count_) { + LLVMTypeRef struct_type = lb_type(m, t); + GB_ASSERT(LLVMGetTypeKind(struct_type) == LLVMStructTypeKind); + + unsigned value_count = cast(unsigned)value_count_; + unsigned elem_count = LLVMCountStructElementTypes(struct_type); + if (elem_count == value_count) { + return llvm_const_named_struct(struct_type, values, value_count_); + } + Type *bt = base_type(t); + GB_ASSERT(bt->kind == Type_Struct); + + GB_ASSERT(value_count_ == bt->Struct.fields.count); + + unsigned field_offset = 0; + if (lb_struct_has_padding_prefix(bt)) { + field_offset = 1; + } + + unsigned values_with_padding_count = field_offset + cast(unsigned)(bt->Struct.fields.count*2 + 1); + LLVMValueRef *values_with_padding = gb_alloc_array(permanent_allocator(), LLVMValueRef, values_with_padding_count); + for (unsigned i = 0; i < value_count; i++) { + values_with_padding[field_offset + i*2 + 1] = values[i]; + } + for (unsigned i = 0; i < values_with_padding_count; i++) { + if (values_with_padding[i] == nullptr) { + values_with_padding[i] = LLVMConstNull(LLVMStructGetTypeAtIndex(struct_type, i)); + } + } + + return llvm_const_named_struct(struct_type, values_with_padding, values_with_padding_count); +} LLVMValueRef llvm_const_named_struct(LLVMTypeRef t, LLVMValueRef *values, isize value_count_) { unsigned value_count = cast(unsigned)value_count_; unsigned elem_count = LLVMCountStructElementTypes(t); - GB_ASSERT(value_count == elem_count); + GB_ASSERT_MSG(value_count == elem_count, "%s %u %u", LLVMPrintTypeToString(t), value_count, elem_count); for (unsigned i = 0; i < elem_count; i++) { LLVMTypeRef elem_type = LLVMStructGetTypeAtIndex(t, i); values[i] = llvm_const_cast(values[i], elem_type); @@ -235,7 +267,7 @@ lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, To fields[3]/*procedure*/ = lb_find_or_add_entity_string(p->module, procedure).value; lbValue res = {}; - res.value = llvm_const_named_struct(lb_type(m, t_source_code_location), fields, gb_count_of(fields)); + res.value = llvm_const_named_struct(m, t_source_code_location, fields, gb_count_of(fields)); res.type = t_source_code_location; return res; } @@ -422,7 +454,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true); LLVMValueRef values[2] = {ptr, len}; - res.value = llvm_const_named_struct(lb_type(m, original_type), values, 2); + res.value = llvm_const_named_struct(m, original_type, values, 2); return res; } } @@ -512,7 +544,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc LLVMValueRef values[2] = {ptr, str_len}; GB_ASSERT(is_type_string(original_type)); - res.value = llvm_const_named_struct(lb_type(m, original_type), values, 2); + res.value = llvm_const_named_struct(m, original_type, values, 2); } return res; @@ -554,7 +586,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc break; } - res.value = llvm_const_named_struct(lb_type(m, original_type), values, 2); + res.value = llvm_const_named_struct(m, original_type, values, 2); return res; } break; @@ -585,7 +617,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc break; } - res.value = llvm_const_named_struct(lb_type(m, original_type), values, 4); + res.value = llvm_const_named_struct(m, original_type, values, 4); return res; } break; @@ -802,11 +834,15 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc } isize offset = 0; - if (type->Struct.custom_align > 0) { + if (lb_struct_has_padding_prefix(type)) { offset = 1; } + + LLVMTypeRef struct_type = lb_type(m, original_type); - isize value_count = type->Struct.fields.count + offset; + unsigned value_count = cast(unsigned)(offset + type->Struct.fields.count*2 + 1); + GB_ASSERT(LLVMCountStructElementTypes(struct_type) == value_count); + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, value_count); bool *visited = gb_alloc_array(temporary_allocator(), bool, value_count); @@ -822,9 +858,11 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc Selection sel = lookup_field(type, name, false); Entity *f = type->Struct.fields[sel.index[0]]; + + isize index = offset + f->Variable.field_index*2 + 1; if (elem_type_can_be_constant(f->type)) { - values[offset+f->Variable.field_index] = lb_const_value(m, f->type, tav.value, allow_local).value; - visited[offset+f->Variable.field_index] = true; + values[index] = lb_const_value(m, f->type, tav.value, allow_local).value; + visited[index] = true; } } } else { @@ -835,25 +873,24 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc if (tav.mode != Addressing_Invalid) { val = tav.value; } + + isize index = offset + f->Variable.field_index*2 + 1; if (elem_type_can_be_constant(f->type)) { - values[offset+f->Variable.field_index] = lb_const_value(m, f->type, val, allow_local).value; - visited[offset+f->Variable.field_index] = true; + values[index] = lb_const_value(m, f->type, val, allow_local).value; + visited[index] = true; } } } } - for (isize i = 0; i < type->Struct.fields.count; i++) { - if (!visited[offset+i]) { - GB_ASSERT(values[offset+i] == nullptr); - values[offset+i] = lb_const_nil(m, get_struct_field_type(type, i)).value; + for (isize i = 0; i < value_count; i++) { + if (!visited[i]) { + GB_ASSERT(values[i] == nullptr); + LLVMTypeRef type = LLVMStructGetTypeAtIndex(struct_type, cast(unsigned)i); + values[i] = LLVMConstNull(type); } } - if (type->Struct.custom_align > 0) { - values[0] = LLVMConstNull(lb_alignment_prefix_type_hack(m, type->Struct.custom_align)); - } - bool is_constant = true; for (isize i = 0; i < value_count; i++) { @@ -866,7 +903,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc } if (is_constant) { - res.value = llvm_const_named_struct(lb_type(m, original_type), values, cast(unsigned)value_count); + res.value = llvm_const_named_struct(struct_type, values, cast(unsigned)value_count); return res; } else { // TODO(bill): THIS IS HACK BUT IT WORKS FOR WHAT I NEED @@ -880,8 +917,7 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bool allow_loc new_values[i] = LLVMConstNull(LLVMTypeOf(old_value)); } } - LLVMValueRef constant_value = llvm_const_named_struct(lb_type(m, original_type), new_values, cast(unsigned)value_count); - + LLVMValueRef constant_value = llvm_const_named_struct(struct_type, new_values, cast(unsigned)value_count); GB_ASSERT(is_local); lbProcedure *p = m->curr_procedure; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index a34e98f2b..b2ef6d0d0 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1923,9 +1923,9 @@ lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, lbValue x) { lbValue map_ptr = lb_address_from_load_or_generate_local(p, x); unsigned indices[2] = {0, 0}; - LLVMValueRef hashes_data = LLVMBuildStructGEP(p->builder, map_ptr.value, 0, ""); - LLVMValueRef hashes_data_ptr_ptr = LLVMBuildStructGEP(p->builder, hashes_data, 0, ""); - LLVMValueRef hashes_data_ptr = LLVMBuildLoad(p->builder, hashes_data_ptr_ptr, ""); + lbValue hashes_data = lb_emit_struct_ep(p, map_ptr, 0); + lbValue hashes_data_ptr_ptr = lb_emit_struct_ep(p, hashes_data, 0); + LLVMValueRef hashes_data_ptr = LLVMBuildLoad(p->builder, hashes_data_ptr_ptr.value, ""); if (op_kind == Token_CmpEq) { res.value = LLVMBuildIsNull(p->builder, hashes_data_ptr, ""); @@ -2786,7 +2786,7 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { bool deref = is_type_pointer(t); t = base_type(type_deref(t)); - if (is_type_soa_struct(t)) { + if (is_type_soa_struct(t)) { // SOA STRUCTURES!!!! lbValue val = lb_build_addr_ptr(p, ie->expr); if (deref) { @@ -2821,7 +2821,6 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) { // lbValue len = ir_soa_struct_len(p, base_struct); // lb_emit_bounds_check(p, ast_token(ie->index), index, len); } - lbValue val = lb_emit_ptr_offset(p, field, index); return lb_addr(val); } diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 85fd9153d..b6959c425 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1109,7 +1109,7 @@ lbValue lb_emit_union_tag_ptr(lbProcedure *p, lbValue u) { LLVMTypeRef uvt = LLVMGetElementType(LLVMTypeOf(u.value)); unsigned element_count = LLVMCountStructElementTypes(uvt); - GB_ASSERT_MSG(element_count == 3, "(%s) != (%s)", type_to_string(ut), LLVMPrintTypeToString(uvt)); + GB_ASSERT_MSG(element_count == 3, "element_count=%u (%s) != (%s)", element_count, type_to_string(ut), LLVMPrintTypeToString(uvt)); lbValue tag_ptr = {}; tag_ptr.value = LLVMBuildStructGEP(p->builder, u.value, 2, ""); @@ -1160,13 +1160,9 @@ LLVMTypeRef lb_alignment_prefix_type_hack(lbModule *m, i64 alignment) { return LLVMArrayType(lb_type(m, t_u32), 0); case 8: return LLVMArrayType(lb_type(m, t_u64), 0); - case 16: + default: case 16: return LLVMArrayType(LLVMVectorType(lb_type(m, t_u32), 4), 0); - default: - GB_PANIC("Invalid alignment %d", cast(i32)alignment); - break; } - return nullptr; } String lb_mangle_name(lbModule *m, Entity *e) { @@ -1650,11 +1646,17 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { GB_ASSERT(field_count == 2); LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count); - LLVMTypeRef entries_fields[4] = { - lb_type(m, t_rawptr), + LLVMTypeRef padding_type = LLVMArrayType(lb_type(m, t_uintptr), 0); + LLVMTypeRef entries_fields[] = { + padding_type, + lb_type(m, t_rawptr), // data + padding_type, lb_type(m, t_int), // len + padding_type, lb_type(m, t_int), // cap + padding_type, lb_type(m, t_allocator), // allocator + padding_type, }; fields[0] = lb_type(m, internal_type->Struct.fields[0]->type); @@ -1676,25 +1678,63 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { } isize offset = 0; - if (type->Struct.custom_align > 0) { + if (lb_struct_has_padding_prefix(type)) { offset = 1; } m->internal_type_level += 1; defer (m->internal_type_level -= 1); - unsigned field_count = cast(unsigned)(type->Struct.fields.count + offset); + unsigned field_count = cast(unsigned)(offset + type->Struct.fields.count*2 + 1); LLVMTypeRef *fields = gb_alloc_array(temporary_allocator(), LLVMTypeRef, field_count); + LLVMTypeRef type_u8 = lb_type(m, t_u8); + LLVMTypeRef type_u16 = lb_type(m, t_u16); + LLVMTypeRef type_u32 = lb_type(m, t_u32); + LLVMTypeRef type_u64 = lb_type(m, t_u64); + + i64 padding_offset = 0; for_array(i, type->Struct.fields) { Entity *field = type->Struct.fields[i]; - fields[i+offset] = lb_type(m, field->type); - } + i64 padding = type->Struct.offsets[i]-padding_offset; + LLVMTypeRef padding_type = nullptr; + if (padding_offset == 0) { + padding_type = lb_alignment_prefix_type_hack(m, type_align_of(type)); + } else { + i64 alignment = type_align_of(field->type); + // NOTE(bill): limit to `[N x u64]` to prevent ABI issues + alignment = gb_min(alignment, 8); + if (padding % alignment == 0) { + isize len = padding/alignment; + switch (alignment) { + case 1: padding_type = LLVMArrayType(type_u8, cast(unsigned)len); break; + case 2: padding_type = LLVMArrayType(type_u16, cast(unsigned)len); break; + case 4: padding_type = LLVMArrayType(type_u32, cast(unsigned)len); break; + case 8: padding_type = LLVMArrayType(type_u64, cast(unsigned)len); break; + } + } else { + padding_type = LLVMArrayType(type_u8, cast(unsigned)padding); + } + } + fields[offset + i*2 + 0] = padding_type; + fields[offset + i*2 + 1] = lb_type(m, field->type); + if (!type->Struct.is_packed) { + padding_offset = align_formula(padding_offset, type_align_of(field->type)); + } + padding_offset += type_size_of(field->type); + } + + i64 end_padding = type_size_of(type)-padding_offset; + fields[field_count-1] = LLVMArrayType(type_u8, cast(unsigned)end_padding); - if (type->Struct.custom_align > 0) { + if (offset != 0) { + GB_ASSERT(offset == 1); fields[0] = lb_alignment_prefix_type_hack(m, type->Struct.custom_align); } + for (unsigned i = 0; i < field_count; i++) { + GB_ASSERT(fields[i] != nullptr); + } return LLVMStructTypeInContext(ctx, fields, field_count, type->Struct.is_packed); } @@ -2230,7 +2270,7 @@ lbValue lb_find_or_add_entity_string(lbModule *m, String const &str) { LLVMValueRef values[2] = {ptr, str_len}; lbValue res = {}; - res.value = llvm_const_named_struct(lb_type(m, t_string), values, 2); + res.value = llvm_const_named_struct(m, t_string, values, 2); res.type = t_string; return res; } @@ -2265,7 +2305,7 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str) LLVMValueRef values[2] = {ptr, len}; lbValue res = {}; - res.value = llvm_const_named_struct(lb_type(m, t_u8_slice), values, 2); + res.value = llvm_const_named_struct(m, t_u8_slice, values, 2); res.type = t_u8_slice; return res; } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index ac922b642..82ad199bb 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -357,8 +357,7 @@ void lb_build_range_indexed(lbProcedure *p, lbValue expr, Type *val_type, lbValu lbValue entries = lb_map_entries_ptr(p, expr); lbValue elem = lb_emit_struct_ep(p, entries, 0); elem = lb_emit_load(p, elem); - - lbValue entry = lb_emit_ptr_offset(p, elem, idx); + lbValue entry = lb_emit_ptr_offset(p, elem, idx); idx = lb_emit_load(p, lb_emit_struct_ep(p, entry, 2)); val = lb_emit_load(p, lb_emit_struct_ep(p, entry, 3)); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index f17b8df6a..1defadca3 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -157,12 +157,14 @@ lbValue lb_type_info_member_tags_offset(lbProcedure *p, isize count) { void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info data lbModule *m = p->module; CheckerInfo *info = m->info; - + + i64 global_type_info_data_entity_count = 0; { // NOTE(bill): Set the type_table slice with the global backing array lbValue global_type_table = lb_find_runtime_value(m, str_lit("type_table")); Type *type = base_type(lb_global_type_info_data_entity->type); GB_ASSERT(is_type_array(type)); + global_type_info_data_entity_count = type->Array.count; LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; LLVMValueRef values[2] = { @@ -179,6 +181,11 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da Entity *type_info_flags_entity = find_core_entity(info->checker, str_lit("Type_Info_Flags")); Type *t_type_info_flags = type_info_flags_entity->type; + + auto entries_handled = slice_make(heap_allocator(), cast(isize)global_type_info_data_entity_count); + defer (gb_free(heap_allocator(), entries_handled.data)); + entries_handled[0] = true; + for_array(type_info_type_index, info->type_info_types) { Type *t = info->type_info_types[type_info_type_index]; if (t == nullptr || t == t_invalid) { @@ -189,19 +196,36 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da if (entry_index <= 0) { continue; } + + if (entries_handled[entry_index]) { + continue; + } + entries_handled[entry_index] = true; + lbValue global_data_ptr = lb_global_type_info_data_ptr(m); lbValue tag = {}; - lbValue ti_ptr = lb_emit_array_epi(p, lb_global_type_info_data_ptr(m), cast(i32)entry_index); + lbValue ti_ptr = lb_emit_array_epi(p, global_data_ptr, cast(i32)entry_index); + + i64 size = type_size_of(t); + i64 align = type_align_of(t); + u32 flags = type_info_flags_of_type(t); + lbValue id = lb_typeid(m, t); + GB_ASSERT_MSG(align != 0, "%lld %s", align, type_to_string(t)); + + lbValue type_info_flags = lb_const_int(p->module, t_type_info_flags, flags); + + lbValue size_ptr = lb_emit_struct_ep(p, ti_ptr, 0); + lbValue align_ptr = lb_emit_struct_ep(p, ti_ptr, 1); + lbValue flags_ptr = lb_emit_struct_ep(p, ti_ptr, 2); + lbValue id_ptr = lb_emit_struct_ep(p, ti_ptr, 3); + + lb_emit_store(p, size_ptr, lb_const_int(m, t_int, size)); + lb_emit_store(p, align_ptr, lb_const_int(m, t_int, align)); + lb_emit_store(p, flags_ptr, type_info_flags); + lb_emit_store(p, id_ptr, id); + lbValue variant_ptr = lb_emit_struct_ep(p, ti_ptr, 4); - lbValue type_info_flags = lb_const_int(p->module, t_type_info_flags, type_info_flags_of_type(t)); - - lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 0), lb_const_int(m, t_int, type_size_of(t))); - lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 1), lb_const_int(m, t_int, type_align_of(t))); - lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 2), type_info_flags); - lb_emit_store(p, lb_emit_struct_ep(p, ti_ptr, 3), lb_typeid(m, t)); - - switch (t->kind) { case Type_Named: { tag = lb_const_ptr_cast(m, variant_ptr, t_type_info_named_ptr); @@ -233,7 +257,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -298,7 +322,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -334,7 +358,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } break; @@ -368,7 +392,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } break; @@ -393,7 +417,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -407,7 +431,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -423,7 +447,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -443,7 +467,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); // NOTE(bill): Union assignment @@ -467,7 +491,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -481,7 +505,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -506,7 +530,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -545,7 +569,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; @@ -596,7 +620,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } break; @@ -650,7 +674,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } @@ -688,7 +712,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da vals[11] = soa_len.value; } } - + isize count = t->Struct.fields.count; if (count > 0) { lbValue memory_types = lb_type_info_member_types_offset (p, count); @@ -743,11 +767,10 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag.type, i))); } } - - + lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; @@ -767,7 +790,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); break; } @@ -791,7 +814,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } break; @@ -808,7 +831,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } break; @@ -823,7 +846,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } break; @@ -837,7 +860,7 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da lbValue res = {}; res.type = type_deref(tag.type); - res.value = llvm_const_named_struct(lb_type(m, res.type), vals, gb_count_of(vals)); + res.value = llvm_const_named_struct(m, res.type, vals, gb_count_of(vals)); lb_emit_store(p, tag, res); } break; @@ -856,4 +879,10 @@ void lb_setup_type_info_data(lbProcedure *p) { // NOTE(bill): Setup type_info da } } } + + for_array(i, entries_handled) { + if (!entries_handled[i]) { + GB_PANIC("UNHANDLED ENTRY %td (%td)", i, entries_handled.count); + } + } } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 63e27f428..d1613a354 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -807,13 +807,47 @@ lbValue lb_address_from_load(lbProcedure *p, lbValue value) { return {}; } -i32 lb_convert_struct_index(Type *t, i32 index) { - if (t->kind == Type_Struct && t->Struct.custom_align != 0) { - index += 1; +bool lb_struct_has_padding_prefix(Type *t) { + Type *bt = base_type(t); + GB_ASSERT(bt->kind == Type_Struct); + return bt->Struct.custom_align != 0 && bt->Struct.fields.count == 0; +} + +i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) { + if (t->kind == Type_Struct) { + index = index*2 + 1; + if (lb_struct_has_padding_prefix(t)) { + index += 1; + } + + unsigned count = LLVMCountStructElementTypes(lb_type(m, t)); + GB_ASSERT(count >= cast(unsigned)index); } return index; } +char const *llvm_type_kinds[] = { + "LLVMVoidTypeKind", + "LLVMHalfTypeKind", + "LLVMFloatTypeKind", + "LLVMDoubleTypeKind", + "LLVMX86_FP80TypeKind", + "LLVMFP128TypeKind", + "LLVMPPC_FP128TypeKind", + "LLVMLabelTypeKind", + "LLVMIntegerTypeKind", + "LLVMFunctionTypeKind", + "LLVMStructTypeKind", + "LLVMArrayTypeKind", + "LLVMPointerTypeKind", + "LLVMVectorTypeKind", + "LLVMMetadataTypeKind", + "LLVMX86_MMXTypeKind", + "LLVMTokenTypeKind", + "LLVMScalableVectorTypeKind", + "LLVMBFloatTypeKind", +}; + lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { GB_ASSERT(is_type_pointer(s.type)); Type *t = base_type(type_deref(s.type)); @@ -878,6 +912,7 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { case 0: result_type = get_struct_field_type(gst, 0); break; case 1: result_type = get_struct_field_type(gst, 1); break; } + index = index*2 + 1; } else if (is_type_array(t)) { return lb_emit_array_epi(p, s, index); } else if (is_type_relative_slice(t)) { @@ -891,7 +926,7 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { GB_ASSERT_MSG(result_type != nullptr, "%s %d", type_to_string(t), index); - index = lb_convert_struct_index(t, index); + index = lb_convert_struct_index(p->module, t, index); if (lb_is_const(s)) { lbModule *m = p->module; @@ -902,6 +937,14 @@ lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { return res; } else { lbValue res = {}; + LLVMTypeRef st = LLVMGetElementType(LLVMTypeOf(s.value)); + // gb_printf_err("%s\n", type_to_string(s.type)); + // gb_printf_err("%s\n", LLVMPrintTypeToString(LLVMTypeOf(s.value))); + // gb_printf_err("%d\n", index); + GB_ASSERT_MSG(LLVMGetTypeKind(st) == LLVMStructTypeKind, "%s", llvm_type_kinds[LLVMGetTypeKind(st)]); + unsigned count = LLVMCountStructElementTypes(st); + GB_ASSERT(count >= cast(unsigned)index); + res.value = LLVMBuildStructGEP(p->builder, s.value, cast(unsigned)index, ""); res.type = alloc_type_pointer(result_type); return res; @@ -1013,7 +1056,7 @@ lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { GB_ASSERT_MSG(result_type != nullptr, "%s, %d", type_to_string(s.type), index); - index = lb_convert_struct_index(t, index); + index = lb_convert_struct_index(p->module, t, index); lbValue res = {}; res.value = LLVMBuildExtractValue(p->builder, s.value, cast(unsigned)index, ""); @@ -1232,7 +1275,7 @@ lbValue lb_map_entries_ptr(lbProcedure *p, lbValue value) { GB_ASSERT_MSG(t->kind == Type_Map, "%s", type_to_string(t)); init_map_internal_types(t); i32 index = 1; - lbValue entries = lb_emit_struct_ep(p, value, index); + lbValue entries = lb_emit_struct_ep(p, value, index); return entries; } -- cgit v1.2.3