From 667aa3671e585fb348a2e05ddf0992c637b40ec4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 1 Mar 2021 17:54:49 +0000 Subject: [PATCH] Fix Addressing for SOA on store; Add intrinsics.type_struct_field_count(T) --- src/check_expr.cpp | 14 ++++++++++++++ src/checker_builtin_procs.hpp | 5 +++++ src/ir.cpp | 29 +++++++++++++++++++++++------ src/llvm_backend.cpp | 29 +++++++++++++++++++++++------ src/types.cpp | 3 +++ 5 files changed, 68 insertions(+), 12 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index f3a042bd9..a31f1c871 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -5768,6 +5768,20 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } break; + case BuiltinProc_type_struct_field_count: + operand->value = exact_value_i64(0); + if (operand->mode != Addressing_Type) { + error(operand->expr, "Expected a struct type for '%.*s'", LIT(builtin_name)); + } else if (!is_type_struct(operand->type)) { + error(operand->expr, "Expected a struct type for '%.*s'", LIT(builtin_name)); + } else { + Type *bt = base_type(operand->type); + operand->value = exact_value_i64(bt->Struct.fields.count); + } + operand->mode = Addressing_Constant; + operand->type = t_untyped_integer; + break; + case BuiltinProc_type_proc_parameter_count: operand->value = exact_value_i64(0); if (operand->mode != Addressing_Type) { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index b5b5667af..f648c8027 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -171,6 +171,8 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_is_specialization_of, + BuiltinProc_type_struct_field_count, + BuiltinProc_type_proc_parameter_count, BuiltinProc_type_proc_return_count, @@ -357,6 +359,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_has_field"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_specialization_of"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("type_struct_field_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_proc_parameter_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_proc_return_count"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/ir.cpp b/src/ir.cpp index 4841402f5..c54e91f17 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -3932,22 +3932,39 @@ void ir_addr_store(irProcedure *proc, irAddr addr, irValue *value) { Type *t = type_deref(ir_type(addr.addr)); t = base_type(t); GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None); - value = ir_emit_conv(proc, value, t->Struct.soa_elem); + Type *elem_type = t->Struct.soa_elem; + value = ir_emit_conv(proc, value, elem_type); + elem_type = base_type(elem_type); irValue *index = addr.soa.index; if (index->kind != irValue_Constant || t->Struct.soa_kind != StructSoa_Fixed) { Type *t = base_type(type_deref(ir_type(addr.addr))); GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None); - i64 count = t->Struct.soa_count; - irValue *len = ir_const_int(count); + irValue *len = ir_soa_struct_len(proc, addr.addr); ir_emit_bounds_check(proc, ast_token(addr.soa.index_expr), index, len); } - for_array(i, t->Struct.fields) { + isize field_count = 0; + + switch (elem_type->kind) { + case Type_Struct: + field_count = elem_type->Struct.fields.count; + break; + case Type_Array: + field_count = elem_type->Array.count; + break; + } + for (isize i = 0; i < field_count; i++) { irValue *dst = ir_emit_struct_ep(proc, addr.addr, cast(i32)i); - dst = ir_emit_array_ep(proc, dst, index); irValue *src = ir_emit_struct_ev(proc, value, cast(i32)i); - ir_emit_store(proc, dst, src); + if (t->Struct.soa_kind == StructSoa_Fixed) { + dst = ir_emit_array_ep(proc, dst, index); + ir_emit_store(proc, dst, src); + } else { + irValue *field = ir_emit_load(proc, dst); + dst = ir_emit_ptr_offset(proc, field, index); + ir_emit_store(proc, dst, src); + } } return; } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 7237504ce..123a38cac 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -406,22 +406,39 @@ void lb_addr_store(lbProcedure *p, lbAddr addr, lbValue value) { Type *t = type_deref(addr.addr.type); t = base_type(t); GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None); - value = lb_emit_conv(p, value, t->Struct.soa_elem); + Type *elem_type = t->Struct.soa_elem; + value = lb_emit_conv(p, value, elem_type); + elem_type = base_type(elem_type); lbValue index = addr.soa.index; if (!lb_is_const(index) || t->Struct.soa_kind != StructSoa_Fixed) { Type *t = base_type(type_deref(addr.addr.type)); GB_ASSERT(t->kind == Type_Struct && t->Struct.soa_kind != StructSoa_None); - i64 count = t->Struct.soa_count; - lbValue len = lb_const_int(p->module, t_int, count); + lbValue len = lb_soa_struct_len(p, addr.addr); lb_emit_bounds_check(p, ast_token(addr.soa.index_expr), index, len); } - for_array(i, t->Struct.fields) { + isize field_count = 0; + + switch (elem_type->kind) { + case Type_Struct: + field_count = elem_type->Struct.fields.count; + break; + case Type_Array: + field_count = elem_type->Array.count; + break; + } + for (isize i = 0; i < field_count; i++) { lbValue dst = lb_emit_struct_ep(p, addr.addr, cast(i32)i); - dst = lb_emit_array_ep(p, dst, index); lbValue src = lb_emit_struct_ev(p, value, cast(i32)i); - lb_emit_store(p, dst, src); + if (t->Struct.soa_kind == StructSoa_Fixed) { + dst = lb_emit_array_ep(p, dst, index); + lb_emit_store(p, dst, src); + } else { + lbValue field = lb_emit_load(p, dst); + dst = lb_emit_ptr_offset(p, field, index); + lb_emit_store(p, dst, src); + } } return; } diff --git a/src/types.cpp b/src/types.cpp index 793829d0e..b714b7798 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -1865,6 +1865,9 @@ bool is_type_comparable(Type *t) { if (type_size_of(t) == 0) { return false; } + if (t->Struct.soa_kind != StructSoa_None) { + return false; + } if (t->Struct.is_raw_union) { return is_type_simple_compare(t); }