From 1404437324a80dd9a717bcc1c0af338e97a11a54 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Sun, 29 Mar 2026 19:37:49 +0300 Subject: [PATCH] IR & Aarch64 compiler arrays support wip --- examples/ir_test.psl | 20 +-- libs/ast/source/type_check.cpp | 29 +++- libs/ir/source/compiler.cpp | 92 +++++++++++-- libs/jit/source/arch/aarch64/compiler_v2.cpp | 133 ++++++++++++------- 4 files changed, 196 insertions(+), 78 deletions(-) diff --git a/examples/ir_test.psl b/examples/ir_test.psl index c65b2dc..8297680 100644 --- a/examples/ir_test.psl +++ b/examples/ir_test.psl @@ -63,21 +63,9 @@ struct ray: func intersect_plane(ray: ray, normal: vec3, value: f32) -> f32: return (value - dot(ray.origin, normal)) / dot(ray.direction, normal) -mut v = vec3(1.0, 2.0, 3.0) -mut u = vec3(1.0, 2.0, 3.0) -let p = &mut u -p[4].x = 4.0 -print_vec3(v) -print('\n') -print_i32(((p + 5) - p) as i32) +mut a = [1, 2, 3] +a[0] = 10 +let p = a as i32* +print_i32(p[1]) print('\n') -// Assignment syntax: -// lhs = rhs -// lhs must be an lvalue -// An lvalue can be -// * An identifier -// * A pointer dereference -// * A field of another lvalue -// * Access by index to an lvalue array - diff --git a/libs/ast/source/type_check.cpp b/libs/ast/source/type_check.cpp index 946933c..f13f3f8 100644 --- a/libs/ast/source/type_check.cpp +++ b/libs/ast/source/type_check.cpp @@ -507,9 +507,8 @@ namespace pslang::ast if (types::equal(*source_type, *target_type)) return; - if (std::get_if(target_type.get())) - if (!types::is_bool_type(*source_type) && !types::is_bool_type(*target_type)) - return; + if (types::is_numeric_type(*source_type) && types::is_numeric_type(*target_type)) + return; if (auto source_pointer_type = std::get_if(source_type.get())) { @@ -521,6 +520,30 @@ namespace pslang::ast } } + if (auto source_array_type = std::get_if(source_type.get())) + { + if (auto target_pointer_type = std::get_if(target_type.get())) + { + if (auto lvalue = classify_lvalue(node.expression)) + { + if (target_pointer_type->is_mutable && *lvalue != ast::value_category::_mutable) + throw type_error("Cannot cast a non-mutable array to a mutable pointer", node.location); + if (!types::equal(*source_array_type->element_type, *target_pointer_type->referenced_type)) + { + std::ostringstream os; + os << "Cannot cast an array of "; + ast::print(os, *source_array_type->element_type); + os << " to a pointer to a different type "; + ast::print(os, *target_pointer_type->referenced_type); + throw type_error(os.str(), node.location); + } + return; + } + else + throw type_error("Cannot cast a non-lvalue array to a pointer", node.location); + } + } + std::ostringstream os; os << "Cannot cast a value of type "; print(os, *source_type); diff --git a/libs/ir/source/compiler.cpp b/libs/ir/source/compiler.cpp index edd2fee..be7439d 100644 --- a/libs/ir/source/compiler.cpp +++ b/libs/ir/source/compiler.cpp @@ -369,16 +369,60 @@ namespace pslang::ir } } + node_ref apply(ast::array const & node) + { + mcontext.nodes->emplace_back(alloc{}, node.inferred_type); + auto array = last(); + for (std::size_t i = 0; i < node.elements.size(); ++i) + { + auto element = apply(node.elements[i]); + mcontext.nodes->emplace_back(assignment{array, element, {i}}); + } + return array; + } + node_ref apply(ast::array_access const & node) { - auto array_type = ast::get_type(*node.array); - if (types::is_pointer_type(*array_type)) + auto object_type = ast::get_type(*node.array); + auto array_type = std::get_if(object_type.get()); + auto pointer_type = std::get_if(object_type.get()); + + if (array_type || pointer_type) { - auto new_ptr = apply(ast::binary_operation{ast::binary_operation_type::addition, node.array, node.index, {}, array_type}); - mcontext.nodes->emplace_back(load{new_ptr}, node.inferred_type); + types::type_ptr element_type; + if (array_type) + element_type = array_type->element_type; + else // if (pointer_type) + element_type = pointer_type->referenced_type; + + auto target_pointer_type = std::make_shared(types::pointer_type{element_type, true}); + + node_ref base_ptr; + if (array_type) + { + auto array = apply(*node.array); + mcontext.nodes->emplace_back(cast_operation{array, target_pointer_type}, target_pointer_type); + base_ptr = last(); + } + else // if (pointer_type) + { + base_ptr = apply(*node.array); + } + + auto i64_type = std::make_shared(types::primitive_type{types::i64_type{}}); + std::int64_t element_size = ast::type_size(*element_type); + + auto index = apply(*node.index); + mcontext.nodes->emplace_back(cast_operation{index, i64_type}, i64_type); + auto index_cast = last(); + mcontext.nodes->emplace_back(literal{ast::i64_literal{element_size}}, i64_type); + mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::multiplication, index_cast, last()}, i64_type); + mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, base_ptr, last()}, target_pointer_type); + mcontext.nodes->emplace_back(load{last()}, node.inferred_type); return last(); } - throw std::runtime_error("Unknown array access left-hand side"); + else + throw std::runtime_error("Unknown array access left-hand side"); } node_ref apply(ast::field_access const & node) @@ -452,10 +496,42 @@ namespace pslang::ir if (auto array_access = std::get_if(node.get())) { - auto array_type = get_type(*array_access->array); - if (types::is_pointer_type(*array_type)) + auto object_type = get_type(*array_access->array); + auto array_type = std::get_if(object_type.get()); + auto pointer_type = std::get_if(object_type.get()); + + if (array_type || pointer_type) { - return apply(ast::binary_operation{ast::binary_operation_type::addition, array_access->array, array_access->index, {}, array_type}); + types::type_ptr element_type; + if (array_type) + element_type = array_type->element_type; + else // if (pointer_type) + element_type = pointer_type->referenced_type; + + auto target_pointer_type = std::make_shared(types::pointer_type{element_type, true}); + + node_ref base_ptr; + if (array_type) + { + auto array = apply(*array_access->array); + mcontext.nodes->emplace_back(cast_operation{array, target_pointer_type}, target_pointer_type); + base_ptr = last(); + } + else // if (pointer_type) + { + base_ptr = apply(*array_access->array); + } + + auto i64_type = std::make_shared(types::primitive_type{types::i64_type{}}); + std::int64_t element_size = ast::type_size(*element_type); + + auto index = apply(*array_access->index); + mcontext.nodes->emplace_back(cast_operation{index, i64_type}, i64_type); + auto index_cast = last(); + mcontext.nodes->emplace_back(literal{ast::i64_literal{element_size}}, i64_type); + mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::multiplication, index_cast, last()}, i64_type); + mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, base_ptr, last()}, target_pointer_type); + return last(); } } diff --git a/libs/jit/source/arch/aarch64/compiler_v2.cpp b/libs/jit/source/arch/aarch64/compiler_v2.cpp index f05f319..49348ee 100644 --- a/libs/jit/source/arch/aarch64/compiler_v2.cpp +++ b/libs/jit/source/arch/aarch64/compiler_v2.cpp @@ -589,63 +589,84 @@ namespace pslang::jit::aarch64 return; } - if (types::is_integer_type(*src_type)) + if (auto array_type = std::get_if(src_type.get())) { - load(node.arg1, 0); - if (types::is_integer_type(*dst_type)) + if (auto pointer_type = std::get_if(dst_type.get())) { - extend(0, dst_type); - } - else if (types::is_floating_point_type(*dst_type)) - { - auto dst_mode = fp_mode_for(*dst_type); - if (types::is_signed_integer_type(*src_type)) + if (types::equal(*array_type->element_type, *pointer_type->referenced_type)) { - builder.fmov(0, 0, 3, 1); - builder.scvtf(0, 0, 3); - if (dst_mode != 3) - builder.fcvt(0, 3, 0, dst_mode); + std::int32_t offset = stack_size - stack_position.at(node.arg1); + builder.add_imm(31, 0, offset); + store(it, 0); + return; } - else if (types::is_unsigned_integer_type(*src_type)) - { - builder.fmov(0, 0, 3, 1); - builder.ucvtf(0, 0, 3); - if (dst_mode != 3) - builder.fcvt(0, 3, 0, dst_mode); - } - } - } - else if (types::is_floating_point_type(*src_type)) - { - auto src_mode = fp_mode_for(*src_type); - if (types::is_integer_type(*dst_type)) - { - if (types::is_signed_integer_type(*dst_type)) - { - builder.fcvtns(0, 0, src_mode); - extend(0, dst_type); - } - else if (types::is_unsigned_integer_type(*dst_type)) - { - builder.fcvtnu(0, 0, src_mode); - extend(0, dst_type); - } - } - else if (types::is_floating_point_type(*dst_type)) - { - auto dst_mode = fp_mode_for(*dst_type); - builder.fcvt(0, src_mode, 0, dst_mode); } } - if (types::is_integer_type(*dst_type)) + if (types::is_numeric_type(*src_type) && types::is_numeric_type(*dst_type)) { - store(it, 0); - } - else if (types::is_floating_point_type(*dst_type)) - { - store_fp(it, 0, fp_mode_for(*dst_type)); + if (types::is_integer_type(*src_type)) + { + load(node.arg1, 0); + if (types::is_integer_type(*dst_type)) + { + extend(0, dst_type); + } + else if (types::is_floating_point_type(*dst_type)) + { + auto dst_mode = fp_mode_for(*dst_type); + if (types::is_signed_integer_type(*src_type)) + { + builder.fmov(0, 0, 3, 1); + builder.scvtf(0, 0, 3); + if (dst_mode != 3) + builder.fcvt(0, 3, 0, dst_mode); + } + else if (types::is_unsigned_integer_type(*src_type)) + { + builder.fmov(0, 0, 3, 1); + builder.ucvtf(0, 0, 3); + if (dst_mode != 3) + builder.fcvt(0, 3, 0, dst_mode); + } + } + } + else if (types::is_floating_point_type(*src_type)) + { + auto src_mode = fp_mode_for(*src_type); + if (types::is_integer_type(*dst_type)) + { + if (types::is_signed_integer_type(*dst_type)) + { + builder.fcvtns(0, 0, src_mode); + extend(0, dst_type); + } + else if (types::is_unsigned_integer_type(*dst_type)) + { + builder.fcvtnu(0, 0, src_mode); + extend(0, dst_type); + } + } + else if (types::is_floating_point_type(*dst_type)) + { + auto dst_mode = fp_mode_for(*dst_type); + builder.fcvt(0, src_mode, 0, dst_mode); + } + } + + if (types::is_integer_type(*dst_type)) + { + store(it, 0); + } + else if (types::is_floating_point_type(*dst_type)) + { + store_fp(it, 0, fp_mode_for(*dst_type)); + } + + return; } + + throw std::runtime_error("Unknown types for cast instruction"); } void apply(ir::node_ref it, ir::argument const & node, types::type_ptr const & type) @@ -675,9 +696,19 @@ namespace pslang::jit::aarch64 std::size_t dst_offset = stack_size - stack_position.at(node.lhs); for (auto field_id : node.path) { - auto struct_node = std::get(*dst_type).node; - dst_type = struct_node->fields[field_id].inferred_type; - dst_offset = dst_offset + struct_node->fields[field_id].layout.offset; + if (auto struct_type = std::get_if(dst_type.get())) + { + auto struct_node = struct_type->node; + dst_type = struct_node->fields[field_id].inferred_type; + dst_offset += struct_node->fields[field_id].layout.offset; + } + else if (auto array_type = std::get_if(dst_type.get())) + { + dst_type = array_type->element_type; + dst_offset += field_id * ast::type_size(*array_type->element_type); + } + else + throw std::runtime_error("Unknown object type for field assignment"); } copy_memory(31, src_offset, 31, dst_offset, ast::type_size(*dst_type), 0);