Implement pointer support in IR via load/store instructions
This commit is contained in:
parent
0c11b09548
commit
dd3eb5d14b
4 changed files with 87 additions and 15 deletions
|
|
@ -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*)
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,9 +195,38 @@ 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);
|
||||||
auto lhs = apply(*node.lhs);
|
|
||||||
mcontext.nodes.emplace_back(assignment{lhs, rhs}, ast::get_type(*node.rhs));
|
if (std::holds_alternative<ast::identifier>(*node.lhs))
|
||||||
return last();
|
{
|
||||||
|
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<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)
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue