IR & Aarch64 compiler arrays support wip

This commit is contained in:
Nikita Lisitsa 2026-03-29 19:37:49 +03:00
parent 46c33b2acf
commit 1404437324
4 changed files with 196 additions and 78 deletions

View file

@ -63,21 +63,9 @@ struct ray:
func intersect_plane(ray: ray, normal: vec3, value: f32) -> f32: func intersect_plane(ray: ray, normal: vec3, value: f32) -> f32:
return (value - dot(ray.origin, normal)) / dot(ray.direction, normal) return (value - dot(ray.origin, normal)) / dot(ray.direction, normal)
mut v = vec3(1.0, 2.0, 3.0) mut a = [1, 2, 3]
mut u = vec3(1.0, 2.0, 3.0) a[0] = 10
let p = &mut u let p = a as i32*
p[4].x = 4.0 print_i32(p[1])
print_vec3(v)
print('\n')
print_i32(((p + 5) - p) as i32)
print('\n') 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

View file

@ -507,8 +507,7 @@ namespace pslang::ast
if (types::equal(*source_type, *target_type)) if (types::equal(*source_type, *target_type))
return; return;
if (std::get_if<types::primitive_type>(target_type.get())) if (types::is_numeric_type(*source_type) && types::is_numeric_type(*target_type))
if (!types::is_bool_type(*source_type) && !types::is_bool_type(*target_type))
return; return;
if (auto source_pointer_type = std::get_if<types::pointer_type>(source_type.get())) if (auto source_pointer_type = std::get_if<types::pointer_type>(source_type.get()))
@ -521,6 +520,30 @@ namespace pslang::ast
} }
} }
if (auto source_array_type = std::get_if<types::array_type>(source_type.get()))
{
if (auto target_pointer_type = std::get_if<types::pointer_type>(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; std::ostringstream os;
os << "Cannot cast a value of type "; os << "Cannot cast a value of type ";
print(os, *source_type); print(os, *source_type);

View file

@ -369,15 +369,59 @@ 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) node_ref apply(ast::array_access const & node)
{ {
auto array_type = ast::get_type(*node.array); auto object_type = ast::get_type(*node.array);
if (types::is_pointer_type(*array_type)) auto array_type = std::get_if<types::array_type>(object_type.get());
auto pointer_type = std::get_if<types::pointer_type>(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}); types::type_ptr element_type;
mcontext.nodes->emplace_back(load{new_ptr}, node.inferred_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::type>(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::type>(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(); return last();
} }
else
throw std::runtime_error("Unknown array access left-hand side"); throw std::runtime_error("Unknown array access left-hand side");
} }
@ -452,10 +496,42 @@ namespace pslang::ir
if (auto array_access = std::get_if<ast::array_access>(node.get())) if (auto array_access = std::get_if<ast::array_access>(node.get()))
{ {
auto array_type = get_type(*array_access->array); auto object_type = get_type(*array_access->array);
if (types::is_pointer_type(*array_type)) auto array_type = std::get_if<types::array_type>(object_type.get());
auto pointer_type = std::get_if<types::pointer_type>(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::type>(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::type>(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();
} }
} }

View file

@ -589,6 +589,22 @@ namespace pslang::jit::aarch64
return; return;
} }
if (auto array_type = std::get_if<types::array_type>(src_type.get()))
{
if (auto pointer_type = std::get_if<types::pointer_type>(dst_type.get()))
{
if (types::equal(*array_type->element_type, *pointer_type->referenced_type))
{
std::int32_t offset = stack_size - stack_position.at(node.arg1);
builder.add_imm(31, 0, offset);
store(it, 0);
return;
}
}
}
if (types::is_numeric_type(*src_type) && types::is_numeric_type(*dst_type))
{
if (types::is_integer_type(*src_type)) if (types::is_integer_type(*src_type))
{ {
load(node.arg1, 0); load(node.arg1, 0);
@ -646,6 +662,11 @@ namespace pslang::jit::aarch64
{ {
store_fp(it, 0, fp_mode_for(*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) 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); std::size_t dst_offset = stack_size - stack_position.at(node.lhs);
for (auto field_id : node.path) for (auto field_id : node.path)
{ {
auto struct_node = std::get<types::struct_type>(*dst_type).node; if (auto struct_type = std::get_if<types::struct_type>(dst_type.get()))
{
auto struct_node = struct_type->node;
dst_type = struct_node->fields[field_id].inferred_type; dst_type = struct_node->fields[field_id].inferred_type;
dst_offset = dst_offset + struct_node->fields[field_id].layout.offset; dst_offset += struct_node->fields[field_id].layout.offset;
}
else if (auto array_type = std::get_if<types::array_type>(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); copy_memory(31, src_offset, 31, dst_offset, ast::type_size(*dst_type), 0);