diff --git a/examples/ir_test.psl b/examples/ir_test.psl index 1d4969d..93bbd54 100644 --- a/examples/ir_test.psl +++ b/examples/ir_test.psl @@ -7,7 +7,6 @@ foreign func free(ptr: unit*) let array = alloc(400ul) as i32 mut* *array = 10 *(array + 1) = 20 -let q = array + 10 -let n = q - array -array[5] = 50 +let test = array[10] +array[15] = 1500 free(array as unit*) diff --git a/libs/ir/include/pslang/ir/node.hpp b/libs/ir/include/pslang/ir/node.hpp index ec999cb..522960b 100644 --- a/libs/ir/include/pslang/ir/node.hpp +++ b/libs/ir/include/pslang/ir/node.hpp @@ -25,6 +25,17 @@ namespace pslang::ir node_ref source; }; + struct load + { + node_ref ptr; + }; + + struct store + { + node_ref ptr; + node_ref value; + }; + struct unary_operation { ast::unary_operation_type type; @@ -49,7 +60,7 @@ namespace pslang::ir std::size_t index; }; - struct address + struct instruction_address { node_ref target; }; @@ -100,11 +111,13 @@ namespace pslang::ir nop, literal, copy, + load, + store, unary_operation, binary_operation, cast_operation, argument, - address, + instruction_address, extern_symbol, assignment, jump, @@ -122,4 +135,4 @@ namespace pslang::ir types::type_ptr inferred_type = nullptr; }; -} \ No newline at end of file +} diff --git a/libs/ir/source/compiler.cpp b/libs/ir/source/compiler.cpp index 150955c..999fdda 100644 --- a/libs/ir/source/compiler.cpp +++ b/libs/ir/source/compiler.cpp @@ -75,7 +75,7 @@ namespace pslang::ir } else if (node.function_node) { - mcontext.nodes.emplace_back(address{}, node.inferred_type); + mcontext.nodes.emplace_back(instruction_address{}, node.inferred_type); lcontext.resolve_address.emplace_back(last(), node.function_node); return last(); } @@ -91,6 +91,13 @@ namespace pslang::ir node_ref apply(ast::unary_operation const & node) { auto arg1 = apply(*node.arg1); + + if (node.type == ast::unary_operation_type::dereference) + { + mcontext.nodes.emplace_back(load{arg1}, node.inferred_type); + return last(); + } + mcontext.nodes.emplace_back(unary_operation{node.type, arg1}, node.inferred_type); return last(); } @@ -162,6 +169,20 @@ namespace pslang::ir } } + node_ref apply(ast::array_access const & node) + { + auto array = apply(*node.array); + auto index = apply(*node.index); + auto array_type = ast::get_type(*node.array); + if (std::get_if(array_type.get())) + { + mcontext.nodes.emplace_back(binary_operation{ast::binary_operation_type::addition, array, index}, array_type); + mcontext.nodes.emplace_back(load{last()}, node.inferred_type); + return last(); + } + throw std::runtime_error("Unknown array access left-hand side"); + } + // TODO: array, array_access, field_access // Statements @@ -174,9 +195,38 @@ namespace pslang::ir node_ref apply(ast::assignment const & node) { auto rhs = apply(*node.rhs); - auto lhs = apply(*node.lhs); - mcontext.nodes.emplace_back(assignment{lhs, rhs}, ast::get_type(*node.rhs)); - return last(); + + if (std::holds_alternative(*node.lhs)) + { + auto lhs = apply(*node.lhs); + mcontext.nodes.emplace_back(assignment{lhs, rhs}, ast::get_type(*node.rhs)); + return last(); + } + + if (auto array_access = std::get_if(node.lhs.get())) + { + auto array_type = get_type(*array_access->array); + if (std::get_if(array_type.get())) + { + auto base_ptr = apply(*array_access->array); + auto index = apply(*array_access->index); + mcontext.nodes.emplace_back(binary_operation{ast::binary_operation_type::addition, base_ptr, index}, array_type); + mcontext.nodes.emplace_back(store{last(), rhs}, ast::get_type(*node.rhs)); + return last(); + } + } + + if (auto unary_operation = std::get_if(node.lhs.get())) + { + if (unary_operation->type == ast::unary_operation_type::dereference) + { + auto lhs = apply(*unary_operation->arg1); + mcontext.nodes.emplace_back(store{lhs, rhs}, ast::get_type(*node.rhs)); + return last(); + } + } + + throw std::runtime_error("Unknown assignment left-hand side"); } node_ref apply(ast::variable_declaration const & node) @@ -380,7 +430,7 @@ namespace pslang::ir mcontext.nodes.erase(extra_nop); for (auto const & resolve : lcontext.resolve_address) - std::get
(resolve.address->instruction).target = lcontext.functions.at(resolve.target); + std::get(resolve.address->instruction).target = lcontext.functions.at(resolve.target); for (auto const & resolve : lcontext.resolve_call) std::get(resolve.call->instruction).target = lcontext.functions.at(resolve.target); diff --git a/libs/ir/source/print.cpp b/libs/ir/source/print.cpp index 58db033..9170463 100644 --- a/libs/ir/source/print.cpp +++ b/libs/ir/source/print.cpp @@ -23,10 +23,10 @@ namespace pslang::ir out << "not"; break; case ast::unary_operation_type::address_of: - out << "address"; + out << "addr"; break; case ast::unary_operation_type::mutable_address_of: - out << "address"; + out << "addr"; break; case ast::unary_operation_type::dereference: out << "deref"; @@ -204,6 +204,16 @@ namespace pslang::ir out << "copy $" << get_index(instruction.source); } + void operator()(load const & instruction) + { + out << "load $" << get_index(instruction.ptr); + } + + void operator()(store const & instruction) + { + out << "store $" << get_index(instruction.ptr) << " $" << get_index(instruction.value); + } + void operator()(unary_operation const & instruction) { print(out, instruction.type); @@ -226,9 +236,9 @@ namespace pslang::ir out << "arg #" << instruction.index; } - void operator()(address const & instruction) + void operator()(instruction_address const & instruction) { - out << "addr $" << get_index(instruction.target); + out << "iaddr $" << get_index(instruction.target); } void operator()(extern_symbol const & instruction)