IR & Aarch64 compiler arrays support wip
This commit is contained in:
parent
46c33b2acf
commit
1404437324
4 changed files with 196 additions and 78 deletions
|
|
@ -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
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue