Implement pointer support in IR via load/store instructions

This commit is contained in:
Nikita Lisitsa 2026-03-23 15:35:28 +03:00
parent 0c11b09548
commit dd3eb5d14b
4 changed files with 87 additions and 15 deletions

View file

@ -7,7 +7,6 @@ foreign func free(ptr: unit*)
let array = alloc(400ul) as i32 mut* let array = alloc(400ul) as i32 mut*
*array = 10 *array = 10
*(array + 1) = 20 *(array + 1) = 20
let q = array + 10 let test = array[10]
let n = q - array array[15] = 1500
array[5] = 50
free(array as unit*) free(array as unit*)

View file

@ -25,6 +25,17 @@ namespace pslang::ir
node_ref source; node_ref source;
}; };
struct load
{
node_ref ptr;
};
struct store
{
node_ref ptr;
node_ref value;
};
struct unary_operation struct unary_operation
{ {
ast::unary_operation_type type; ast::unary_operation_type type;
@ -49,7 +60,7 @@ namespace pslang::ir
std::size_t index; std::size_t index;
}; };
struct address struct instruction_address
{ {
node_ref target; node_ref target;
}; };
@ -100,11 +111,13 @@ namespace pslang::ir
nop, nop,
literal, literal,
copy, copy,
load,
store,
unary_operation, unary_operation,
binary_operation, binary_operation,
cast_operation, cast_operation,
argument, argument,
address, instruction_address,
extern_symbol, extern_symbol,
assignment, assignment,
jump, jump,

View file

@ -75,7 +75,7 @@ namespace pslang::ir
} }
else if (node.function_node) 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); lcontext.resolve_address.emplace_back(last(), node.function_node);
return last(); return last();
} }
@ -91,6 +91,13 @@ namespace pslang::ir
node_ref apply(ast::unary_operation const & node) node_ref apply(ast::unary_operation const & node)
{ {
auto arg1 = apply(*node.arg1); 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); mcontext.nodes.emplace_back(unary_operation{node.type, arg1}, node.inferred_type);
return last(); 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<types::pointer_type>(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 // TODO: array, array_access, field_access
// Statements // Statements
@ -174,11 +195,40 @@ namespace pslang::ir
node_ref apply(ast::assignment const & node) node_ref apply(ast::assignment const & node)
{ {
auto rhs = apply(*node.rhs); auto rhs = apply(*node.rhs);
if (std::holds_alternative<ast::identifier>(*node.lhs))
{
auto lhs = apply(*node.lhs); auto lhs = apply(*node.lhs);
mcontext.nodes.emplace_back(assignment{lhs, rhs}, ast::get_type(*node.rhs)); mcontext.nodes.emplace_back(assignment{lhs, rhs}, ast::get_type(*node.rhs));
return last(); return last();
} }
if (auto array_access = std::get_if<ast::array_access>(node.lhs.get()))
{
auto array_type = get_type(*array_access->array);
if (std::get_if<types::pointer_type>(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<ast::unary_operation>(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) node_ref apply(ast::variable_declaration const & node)
{ {
auto before = last(); auto before = last();
@ -380,7 +430,7 @@ namespace pslang::ir
mcontext.nodes.erase(extra_nop); mcontext.nodes.erase(extra_nop);
for (auto const & resolve : lcontext.resolve_address) for (auto const & resolve : lcontext.resolve_address)
std::get<address>(resolve.address->instruction).target = lcontext.functions.at(resolve.target); std::get<instruction_address>(resolve.address->instruction).target = lcontext.functions.at(resolve.target);
for (auto const & resolve : lcontext.resolve_call) for (auto const & resolve : lcontext.resolve_call)
std::get<call>(resolve.call->instruction).target = lcontext.functions.at(resolve.target); std::get<call>(resolve.call->instruction).target = lcontext.functions.at(resolve.target);

View file

@ -23,10 +23,10 @@ namespace pslang::ir
out << "not"; out << "not";
break; break;
case ast::unary_operation_type::address_of: case ast::unary_operation_type::address_of:
out << "address"; out << "addr";
break; break;
case ast::unary_operation_type::mutable_address_of: case ast::unary_operation_type::mutable_address_of:
out << "address"; out << "addr";
break; break;
case ast::unary_operation_type::dereference: case ast::unary_operation_type::dereference:
out << "deref"; out << "deref";
@ -204,6 +204,16 @@ namespace pslang::ir
out << "copy $" << get_index(instruction.source); 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) void operator()(unary_operation const & instruction)
{ {
print(out, instruction.type); print(out, instruction.type);
@ -226,9 +236,9 @@ namespace pslang::ir
out << "arg #" << instruction.index; 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) void operator()(extern_symbol const & instruction)