|
|
|
@ -53,14 +53,14 @@ namespace pslang::ir
|
|
|
|
struct zero_literal_visitor
|
|
|
|
struct zero_literal_visitor
|
|
|
|
: types::const_visitor<zero_literal_visitor>
|
|
|
|
: types::const_visitor<zero_literal_visitor>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
module_context & mcontext;
|
|
|
|
compiled_module & module;
|
|
|
|
|
|
|
|
|
|
|
|
using const_visitor::apply;
|
|
|
|
using const_visitor::apply;
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
void apply(types::primitive_type_base<T>)
|
|
|
|
void apply(types::primitive_type_base<T>)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::literal{ast::primitive_literal_base<T>{.value = {}}}},
|
|
|
|
module.nodes->emplace_back(literal{ast::literal{ast::primitive_literal_base<T>{.value = {}}}},
|
|
|
|
std::make_shared<types::type>(types::primitive_type{types::primitive_type_base<T>{}}));
|
|
|
|
std::make_shared<types::type>(types::primitive_type{types::primitive_type_base<T>{}}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -80,7 +80,7 @@ namespace pslang::ir
|
|
|
|
using const_statement_visitor::apply;
|
|
|
|
using const_statement_visitor::apply;
|
|
|
|
using const_expression_visitor::apply;
|
|
|
|
using const_expression_visitor::apply;
|
|
|
|
|
|
|
|
|
|
|
|
module_context & mcontext;
|
|
|
|
compiled_module & module;
|
|
|
|
local_context & lcontext;
|
|
|
|
local_context & lcontext;
|
|
|
|
|
|
|
|
|
|
|
|
template <typename Node>
|
|
|
|
template <typename Node>
|
|
|
|
@ -94,7 +94,7 @@ namespace pslang::ir
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
node_ref apply(ast::primitive_literal_base<T> const & node)
|
|
|
|
node_ref apply(ast::primitive_literal_base<T> const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(literal{node}, ast::get_type(node));
|
|
|
|
module.nodes->emplace_back(literal{node}, ast::get_type(node));
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -115,13 +115,13 @@ namespace pslang::ir
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (node.function_node)
|
|
|
|
else if (node.function_node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(instruction_address{}, node.inferred_type);
|
|
|
|
module.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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (node.foreign_function_node)
|
|
|
|
else if (node.foreign_function_node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(extern_symbol{node.name}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(extern_symbol{node.name}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
@ -134,7 +134,7 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
if (node.type == ast::unary_operation_type::dereference)
|
|
|
|
if (node.type == ast::unary_operation_type::dereference)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(load{arg1}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(load{arg1}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -145,7 +145,7 @@ namespace pslang::ir
|
|
|
|
throw std::runtime_error("Error compiling address of operator");
|
|
|
|
throw std::runtime_error("Error compiling address of operator");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(unary_operation{node.type, arg1}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(unary_operation{node.type, arg1}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -157,29 +157,29 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
if (node.type == ast::binary_operation_type::logical_and)
|
|
|
|
if (node.type == ast::binary_operation_type::logical_and)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(copy{arg1}, ast::get_type(*node.arg1));
|
|
|
|
module.nodes->emplace_back(copy{arg1}, ast::get_type(*node.arg1));
|
|
|
|
auto result = last();
|
|
|
|
auto result = last();
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{result});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{result});
|
|
|
|
auto jump = last();
|
|
|
|
auto jump = last();
|
|
|
|
auto arg2 = apply(*node.arg2);
|
|
|
|
auto arg2 = apply(*node.arg2);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::binary_and, result, arg2}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::binary_and, result, arg2}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(assignment{result, last()});
|
|
|
|
module.nodes->emplace_back(assignment{result, last()});
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
std::get<jump_if_zero>(jump->instruction).target = last();
|
|
|
|
std::get<jump_if_zero>(jump->instruction).target = last();
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (node.type == ast::binary_operation_type::logical_or)
|
|
|
|
if (node.type == ast::binary_operation_type::logical_or)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(copy{arg1}, ast::get_type(*node.arg1));
|
|
|
|
module.nodes->emplace_back(copy{arg1}, ast::get_type(*node.arg1));
|
|
|
|
auto result = last();
|
|
|
|
auto result = last();
|
|
|
|
mcontext.nodes->emplace_back(unary_operation{ast::unary_operation_type::logical_not, result}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(unary_operation{ast::unary_operation_type::logical_not, result}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{last()});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{last()});
|
|
|
|
auto jump = last();
|
|
|
|
auto jump = last();
|
|
|
|
auto arg2 = apply(*node.arg2);
|
|
|
|
auto arg2 = apply(*node.arg2);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::binary_or, result, arg2}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::binary_or, result, arg2}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(assignment{result, last()});
|
|
|
|
module.nodes->emplace_back(assignment{result, last()});
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
std::get<jump_if_zero>(jump->instruction).target = last();
|
|
|
|
std::get<jump_if_zero>(jump->instruction).target = last();
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -206,28 +206,28 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
auto i64_type = std::make_shared<types::type>(types::primitive_type{types::i64_type{}});
|
|
|
|
auto i64_type = std::make_shared<types::type>(types::primitive_type{types::i64_type{}});
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::i64_literal{element_size}}, i64_type);
|
|
|
|
module.nodes->emplace_back(literal{ast::i64_literal{element_size}}, i64_type);
|
|
|
|
auto element_size_node = last();
|
|
|
|
auto element_size_node = last();
|
|
|
|
|
|
|
|
|
|
|
|
if (node.type == ast::binary_operation_type::addition)
|
|
|
|
if (node.type == ast::binary_operation_type::addition)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (arg1_is_pointer)
|
|
|
|
if (arg1_is_pointer)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{arg2, i64_type}, i64_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{arg2, i64_type}, i64_type);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::multiplication, last(), element_size_node}, i64_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::multiplication, last(), element_size_node}, i64_type);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, arg1, last()}, node.inferred_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // if (arg2_is_pointer)
|
|
|
|
else // if (arg2_is_pointer)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{arg1, i64_type}, i64_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{arg1, i64_type}, i64_type);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::multiplication, last(), element_size_node}, i64_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::multiplication, last(), element_size_node}, i64_type);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, arg2, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, arg2, last()}, node.inferred_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (node.type == ast::binary_operation_type::subtraction)
|
|
|
|
else if (node.type == ast::binary_operation_type::subtraction)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::subtraction, arg1, arg2}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::subtraction, arg1, arg2}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::division, last(), element_size_node}, i64_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::division, last(), element_size_node}, i64_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
@ -253,14 +253,14 @@ namespace pslang::ir
|
|
|
|
// Both signed or both unsigned: just cast the smaller one to the larger type
|
|
|
|
// Both signed or both unsigned: just cast the smaller one to the larger type
|
|
|
|
if (arg1_size < arg2_size)
|
|
|
|
if (arg1_size < arg2_size)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{arg1, max_type}, max_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{arg1, max_type}, max_type);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{node.type, last(), arg2}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{node.type, last(), arg2}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{arg2, max_type}, max_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{arg2, max_type}, max_type);
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{node.type, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{node.type, arg1, last()}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -288,32 +288,32 @@ namespace pslang::ir
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Compare with zero first
|
|
|
|
// Compare with zero first
|
|
|
|
zero_literal_visitor{{}, mcontext}.apply(*arg1_type);
|
|
|
|
zero_literal_visitor{{}, module}.apply(*arg1_type);
|
|
|
|
switch (type)
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case ast::binary_operation_type::equals:
|
|
|
|
case ast::binary_operation_type::equals:
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::greater_equals, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::greater_equals, arg1, last()}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{last(), {}});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{last(), {}});
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ast::binary_operation_type::not_equals:
|
|
|
|
case ast::binary_operation_type::not_equals:
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::less, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::less, arg1, last()}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_nonzero{last(), {}});
|
|
|
|
module.nodes->emplace_back(jump_if_nonzero{last(), {}});
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ast::binary_operation_type::less:
|
|
|
|
case ast::binary_operation_type::less:
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::less, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::less, arg1, last()}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_nonzero{last(), {}});
|
|
|
|
module.nodes->emplace_back(jump_if_nonzero{last(), {}});
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ast::binary_operation_type::greater:
|
|
|
|
case ast::binary_operation_type::greater:
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::greater, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::greater, arg1, last()}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{last(), {}});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{last(), {}});
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ast::binary_operation_type::less_equals:
|
|
|
|
case ast::binary_operation_type::less_equals:
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::less_equals, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::less_equals, arg1, last()}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_nonzero{last(), {}});
|
|
|
|
module.nodes->emplace_back(jump_if_nonzero{last(), {}});
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case ast::binary_operation_type::greater_equals:
|
|
|
|
case ast::binary_operation_type::greater_equals:
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::greater_equals, arg1, last()}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::greater_equals, arg1, last()}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{last(), {}});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{last(), {}});
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
@ -332,13 +332,13 @@ namespace pslang::ir
|
|
|
|
else if (max_size == 8)
|
|
|
|
else if (max_size == 8)
|
|
|
|
max_unsigned_type = std::make_unique<types::type>(types::primitive_type{types::u64_type{}});
|
|
|
|
max_unsigned_type = std::make_unique<types::type>(types::primitive_type{types::u64_type{}});
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{arg1, max_unsigned_type}, max_unsigned_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{arg1, max_unsigned_type}, max_unsigned_type);
|
|
|
|
auto new_arg1 = last();
|
|
|
|
auto new_arg1 = last();
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{arg2, max_unsigned_type}, max_unsigned_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{arg2, max_unsigned_type}, max_unsigned_type);
|
|
|
|
auto new_arg2 = last();
|
|
|
|
auto new_arg2 = last();
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{type, new_arg1, new_arg2}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{type, new_arg1, new_arg2}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(assignment{result, last()});
|
|
|
|
module.nodes->emplace_back(assignment{result, last()});
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
if (auto jump_if_zero = std::get_if<ir::jump_if_zero>(&jump_node->instruction))
|
|
|
|
if (auto jump_if_zero = std::get_if<ir::jump_if_zero>(&jump_node->instruction))
|
|
|
|
jump_if_zero->target = last();
|
|
|
|
jump_if_zero->target = last();
|
|
|
|
else if (auto jump_if_nonzero = std::get_if<ir::jump_if_nonzero>(&jump_node->instruction))
|
|
|
|
else if (auto jump_if_nonzero = std::get_if<ir::jump_if_nonzero>(&jump_node->instruction))
|
|
|
|
@ -349,7 +349,7 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
// General case
|
|
|
|
// General case
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{node.type, arg1, arg2}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(binary_operation{node.type, arg1, arg2}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -363,7 +363,7 @@ namespace pslang::ir
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto arg = apply(*node.expression);
|
|
|
|
auto arg = apply(*node.expression);
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{arg, node.inferred_type}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{arg, node.inferred_type}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -378,13 +378,13 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
if (auto identifier = std::get_if<ast::identifier>(node.function.get()); identifier && identifier->function_node)
|
|
|
|
if (auto identifier = std::get_if<ast::identifier>(node.function.get()); identifier && identifier->function_node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(call{{}, std::move(arguments)}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(call{{}, std::move(arguments)}, node.inferred_type);
|
|
|
|
lcontext.resolve_call.emplace_back(last(), identifier->function_node);
|
|
|
|
lcontext.resolve_call.emplace_back(last(), identifier->function_node);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
auto function = apply(*node.function);
|
|
|
|
auto function = apply(*node.function);
|
|
|
|
mcontext.nodes->emplace_back(call_pointer{function, std::move(arguments)}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(call_pointer{function, std::move(arguments)}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // if (node.type)
|
|
|
|
else // if (node.type)
|
|
|
|
@ -392,13 +392,13 @@ namespace pslang::ir
|
|
|
|
auto type = ast::get_type(*node.type);
|
|
|
|
auto type = ast::get_type(*node.type);
|
|
|
|
if (auto struct_type = std::get_if<types::struct_type>(type.get()))
|
|
|
|
if (auto struct_type = std::get_if<types::struct_type>(type.get()))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(alloc{}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(alloc{}, node.inferred_type);
|
|
|
|
auto result = last();
|
|
|
|
auto result = last();
|
|
|
|
for (std::size_t i = 0; i < node.arguments.size(); ++i)
|
|
|
|
for (std::size_t i = 0; i < node.arguments.size(); ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto const & field = struct_type->node->fields[i];
|
|
|
|
auto const & field = struct_type->node->fields[i];
|
|
|
|
auto arg = apply(*node.arguments[i]);
|
|
|
|
auto arg = apply(*node.arguments[i]);
|
|
|
|
mcontext.nodes->emplace_back(assignment{result, arg, {i}}, field.inferred_type);
|
|
|
|
module.nodes->emplace_back(assignment{result, arg, {i}}, field.inferred_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -408,12 +408,12 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
node_ref apply(ast::array const & node)
|
|
|
|
node_ref apply(ast::array const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(alloc{}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(alloc{}, node.inferred_type);
|
|
|
|
auto array = last();
|
|
|
|
auto array = last();
|
|
|
|
for (std::size_t i = 0; i < node.elements.size(); ++i)
|
|
|
|
for (std::size_t i = 0; i < node.elements.size(); ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto element = apply(node.elements[i]);
|
|
|
|
auto element = apply(node.elements[i]);
|
|
|
|
mcontext.nodes->emplace_back(assignment{array, element, {i}});
|
|
|
|
module.nodes->emplace_back(assignment{array, element, {i}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -438,7 +438,7 @@ namespace pslang::ir
|
|
|
|
if (array_type)
|
|
|
|
if (array_type)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto array = apply(*node.array);
|
|
|
|
auto array = apply(*node.array);
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{array, target_pointer_type}, target_pointer_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{array, target_pointer_type}, target_pointer_type);
|
|
|
|
base_ptr = last();
|
|
|
|
base_ptr = last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else // if (pointer_type)
|
|
|
|
else // if (pointer_type)
|
|
|
|
@ -450,12 +450,12 @@ namespace pslang::ir
|
|
|
|
std::int64_t element_size = ast::type_size(*element_type);
|
|
|
|
std::int64_t element_size = ast::type_size(*element_type);
|
|
|
|
|
|
|
|
|
|
|
|
auto index = apply(*node.index);
|
|
|
|
auto index = apply(*node.index);
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{index, i64_type}, i64_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{index, i64_type}, i64_type);
|
|
|
|
auto index_cast = last();
|
|
|
|
auto index_cast = last();
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::i64_literal{element_size}}, i64_type);
|
|
|
|
module.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);
|
|
|
|
module.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);
|
|
|
|
module.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);
|
|
|
|
module.nodes->emplace_back(load{last()}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
@ -478,16 +478,16 @@ namespace pslang::ir
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (pointer_type)
|
|
|
|
if (pointer_type)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::literal{ast::u64_literal{field.layout.offset}}},
|
|
|
|
module.nodes->emplace_back(literal{ast::literal{ast::u64_literal{field.layout.offset}}},
|
|
|
|
std::make_shared<types::type>(types::primitive_type{types::u64_type{}}));
|
|
|
|
std::make_shared<types::type>(types::primitive_type{types::u64_type{}}));
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, object, last()},
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, object, last()},
|
|
|
|
std::make_shared<types::type>(types::pointer_type{field.inferred_type, pointer_type->is_mutable}));
|
|
|
|
std::make_shared<types::type>(types::pointer_type{field.inferred_type, pointer_type->is_mutable}));
|
|
|
|
mcontext.nodes->emplace_back(load{last()}, field.inferred_type);
|
|
|
|
module.nodes->emplace_back(load{last()}, field.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(copy{object, {i}}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(copy{object, {i}}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -497,20 +497,20 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
node_ref apply(ast::if_expression const & node)
|
|
|
|
node_ref apply(ast::if_expression const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(alloc{}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(alloc{}, node.inferred_type);
|
|
|
|
auto result = last();
|
|
|
|
auto result = last();
|
|
|
|
auto condition = apply(*node.condition);
|
|
|
|
auto condition = apply(*node.condition);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{condition});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{condition});
|
|
|
|
auto jump_skip_if_true = last();
|
|
|
|
auto jump_skip_if_true = last();
|
|
|
|
auto true_result = apply(*node.if_true);
|
|
|
|
auto true_result = apply(*node.if_true);
|
|
|
|
mcontext.nodes->emplace_back(assignment{result, true_result}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(assignment{result, true_result}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(jump{});
|
|
|
|
module.nodes->emplace_back(jump{});
|
|
|
|
auto jump_end_if_true = last();
|
|
|
|
auto jump_end_if_true = last();
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
auto after_if_true = last();
|
|
|
|
auto after_if_true = last();
|
|
|
|
auto false_result = apply(*node.if_false);
|
|
|
|
auto false_result = apply(*node.if_false);
|
|
|
|
mcontext.nodes->emplace_back(assignment{result, false_result}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(assignment{result, false_result}, node.inferred_type);
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
auto end = last();
|
|
|
|
auto end = last();
|
|
|
|
|
|
|
|
|
|
|
|
std::get<jump_if_zero>(jump_skip_if_true->instruction).target = after_if_true;
|
|
|
|
std::get<jump_if_zero>(jump_skip_if_true->instruction).target = after_if_true;
|
|
|
|
@ -520,13 +520,13 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
node_ref apply(ast::sizeof_operator const & node)
|
|
|
|
node_ref apply(ast::sizeof_operator const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::literal{ast::u64_literal{ast::type_size(*node.inferred_source_type)}}}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(literal{ast::literal{ast::u64_literal{ast::type_size(*node.inferred_source_type)}}}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
node_ref apply(ast::alignof_operator const & node)
|
|
|
|
node_ref apply(ast::alignof_operator const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::literal{ast::u64_literal{ast::type_alignment(*node.inferred_source_type)}}}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(literal{ast::literal{ast::u64_literal{ast::type_alignment(*node.inferred_source_type)}}}, node.inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -542,7 +542,7 @@ namespace pslang::ir
|
|
|
|
if (auto identifier = std::get_if<ast::identifier>(lhs_node.get()))
|
|
|
|
if (auto identifier = std::get_if<ast::identifier>(lhs_node.get()))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto lhs = apply(*lhs_node);
|
|
|
|
auto lhs = apply(*lhs_node);
|
|
|
|
mcontext.nodes->emplace_back(assignment{lhs, rhs, std::move(path)}, identifier->inferred_type);
|
|
|
|
module.nodes->emplace_back(assignment{lhs, rhs, std::move(path)}, identifier->inferred_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (auto field_access = std::get_if<ast::field_access>(lhs_node.get()))
|
|
|
|
else if (auto field_access = std::get_if<ast::field_access>(lhs_node.get()))
|
|
|
|
@ -572,7 +572,7 @@ namespace pslang::ir
|
|
|
|
if (auto identifier = std::get_if<ast::identifier>(node.get()))
|
|
|
|
if (auto identifier = std::get_if<ast::identifier>(node.get()))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto object = apply(*node);
|
|
|
|
auto object = apply(*node);
|
|
|
|
mcontext.nodes->emplace_back(unary_operation{ast::unary_operation_type::address_of, object}, result_type);
|
|
|
|
module.nodes->emplace_back(unary_operation{ast::unary_operation_type::address_of, object}, result_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -614,11 +614,11 @@ namespace pslang::ir
|
|
|
|
std::int64_t element_size = ast::type_size(*element_type);
|
|
|
|
std::int64_t element_size = ast::type_size(*element_type);
|
|
|
|
|
|
|
|
|
|
|
|
auto index = apply(*array_access->index);
|
|
|
|
auto index = apply(*array_access->index);
|
|
|
|
mcontext.nodes->emplace_back(cast_operation{index, i64_type}, i64_type);
|
|
|
|
module.nodes->emplace_back(cast_operation{index, i64_type}, i64_type);
|
|
|
|
auto index_cast = last();
|
|
|
|
auto index_cast = last();
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::i64_literal{element_size}}, i64_type);
|
|
|
|
module.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);
|
|
|
|
module.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);
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, base_ptr, last()}, target_pointer_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -648,9 +648,9 @@ namespace pslang::ir
|
|
|
|
auto const & field = struct_node->fields[i];
|
|
|
|
auto const & field = struct_node->fields[i];
|
|
|
|
if (field.name == field_access->field_name)
|
|
|
|
if (field.name == field_access->field_name)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::literal{ast::u64_literal{field.layout.offset}}},
|
|
|
|
module.nodes->emplace_back(literal{ast::literal{ast::u64_literal{field.layout.offset}}},
|
|
|
|
std::make_shared<types::type>(types::primitive_type{types::u64_type{}}));
|
|
|
|
std::make_shared<types::type>(types::primitive_type{types::u64_type{}}));
|
|
|
|
mcontext.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, *object_ptr, last()},
|
|
|
|
module.nodes->emplace_back(binary_operation{ast::binary_operation_type::addition, *object_ptr, last()},
|
|
|
|
result_type);
|
|
|
|
result_type);
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -674,7 +674,7 @@ namespace pslang::ir
|
|
|
|
// Otherwise, compile into explicit memory store
|
|
|
|
// Otherwise, compile into explicit memory store
|
|
|
|
if (auto lhs_ptr = apply_get_address(node.lhs))
|
|
|
|
if (auto lhs_ptr = apply_get_address(node.lhs))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(store{*lhs_ptr, rhs}, ast::get_type(*node.rhs));
|
|
|
|
module.nodes->emplace_back(store{*lhs_ptr, rhs}, ast::get_type(*node.rhs));
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -685,17 +685,17 @@ namespace pslang::ir
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (node.global)
|
|
|
|
if (node.global)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(global{.initializer = {0}}, std::make_unique<types::type>(types::primitive_type{types::bool_type{}}));
|
|
|
|
module.nodes->emplace_back(global{.initializer = {0}}, std::make_unique<types::type>(types::primitive_type{types::bool_type{}}));
|
|
|
|
auto guard = last();
|
|
|
|
auto guard = last();
|
|
|
|
mcontext.nodes->emplace_back(global{.initializer = {}}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(global{.initializer = {}}, node.inferred_type);
|
|
|
|
auto result = last();
|
|
|
|
auto result = last();
|
|
|
|
mcontext.nodes->emplace_back(jump_if_nonzero{.condition = guard, .target = {}});
|
|
|
|
module.nodes->emplace_back(jump_if_nonzero{.condition = guard, .target = {}});
|
|
|
|
auto jump = last();
|
|
|
|
auto jump = last();
|
|
|
|
mcontext.nodes->emplace_back(literal{ast::bool_literal{true}}, std::make_unique<types::type>(types::primitive_type{types::bool_type{}}));
|
|
|
|
module.nodes->emplace_back(literal{ast::bool_literal{true}}, std::make_unique<types::type>(types::primitive_type{types::bool_type{}}));
|
|
|
|
mcontext.nodes->emplace_back(assignment{guard, last()});
|
|
|
|
module.nodes->emplace_back(assignment{guard, last()});
|
|
|
|
auto value = apply(*node.initializer);
|
|
|
|
auto value = apply(*node.initializer);
|
|
|
|
mcontext.nodes->emplace_back(assignment{result, value});
|
|
|
|
module.nodes->emplace_back(assignment{result, value});
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
std::get<jump_if_nonzero>(jump->instruction).target = last();
|
|
|
|
std::get<jump_if_nonzero>(jump->instruction).target = last();
|
|
|
|
lcontext.globals[&node] = result;
|
|
|
|
lcontext.globals[&node] = result;
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
@ -708,7 +708,7 @@ namespace pslang::ir
|
|
|
|
// Evaluating variable initializer didn't produce any nodes
|
|
|
|
// Evaluating variable initializer didn't produce any nodes
|
|
|
|
// It must have been just a reference to another variable or smth like that
|
|
|
|
// It must have been just a reference to another variable or smth like that
|
|
|
|
// Introduce a copy node to prevent accidental variable coalescing
|
|
|
|
// Introduce a copy node to prevent accidental variable coalescing
|
|
|
|
mcontext.nodes->emplace_back(copy{result}, node.inferred_type);
|
|
|
|
module.nodes->emplace_back(copy{result}, node.inferred_type);
|
|
|
|
result = last();
|
|
|
|
result = last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lcontext.variables[&node] = result;
|
|
|
|
lcontext.variables[&node] = result;
|
|
|
|
@ -725,7 +725,7 @@ namespace pslang::ir
|
|
|
|
if (block.condition)
|
|
|
|
if (block.condition)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto condition = apply(*block.condition);
|
|
|
|
auto condition = apply(*block.condition);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{condition, {}});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{condition, {}});
|
|
|
|
jump_to_next = last();
|
|
|
|
jump_to_next = last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -733,10 +733,10 @@ namespace pslang::ir
|
|
|
|
apply(*block.statements);
|
|
|
|
apply(*block.statements);
|
|
|
|
lcontext.scopes.pop_back();
|
|
|
|
lcontext.scopes.pop_back();
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(jump{});
|
|
|
|
module.nodes->emplace_back(jump{});
|
|
|
|
jumps_to_end.push_back(last());
|
|
|
|
jumps_to_end.push_back(last());
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
if (jump_to_next)
|
|
|
|
if (jump_to_next)
|
|
|
|
std::get<jump_if_zero>((*jump_to_next)->instruction).target = last();
|
|
|
|
std::get<jump_if_zero>((*jump_to_next)->instruction).target = last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -750,10 +750,10 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
node_ref apply(ast::while_block const & node)
|
|
|
|
node_ref apply(ast::while_block const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
auto begin = last();
|
|
|
|
auto begin = last();
|
|
|
|
auto condition = apply(*node.condition);
|
|
|
|
auto condition = apply(*node.condition);
|
|
|
|
mcontext.nodes->emplace_back(jump_if_zero{condition, {}});
|
|
|
|
module.nodes->emplace_back(jump_if_zero{condition, {}});
|
|
|
|
auto jump_to_end = last();
|
|
|
|
auto jump_to_end = last();
|
|
|
|
|
|
|
|
|
|
|
|
lcontext.loop_scopes.emplace_back();
|
|
|
|
lcontext.loop_scopes.emplace_back();
|
|
|
|
@ -761,8 +761,8 @@ namespace pslang::ir
|
|
|
|
apply(*node.statements);
|
|
|
|
apply(*node.statements);
|
|
|
|
lcontext.scopes.pop_back();
|
|
|
|
lcontext.scopes.pop_back();
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(jump{begin});
|
|
|
|
module.nodes->emplace_back(jump{begin});
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
|
|
|
|
|
|
|
|
auto end = last();
|
|
|
|
auto end = last();
|
|
|
|
std::get<jump_if_zero>(jump_to_end->instruction).target = end;
|
|
|
|
std::get<jump_if_zero>(jump_to_end->instruction).target = end;
|
|
|
|
@ -778,14 +778,14 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
node_ref apply(ast::break_statement const &)
|
|
|
|
node_ref apply(ast::break_statement const &)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(jump{});
|
|
|
|
module.nodes->emplace_back(jump{});
|
|
|
|
lcontext.loop_scopes.back().resolve_break.push_back(last());
|
|
|
|
lcontext.loop_scopes.back().resolve_break.push_back(last());
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
node_ref apply(ast::continue_statement const &)
|
|
|
|
node_ref apply(ast::continue_statement const &)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(jump{});
|
|
|
|
module.nodes->emplace_back(jump{});
|
|
|
|
lcontext.loop_scopes.back().resolve_continue.push_back(last());
|
|
|
|
lcontext.loop_scopes.back().resolve_continue.push_back(last());
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -805,10 +805,10 @@ namespace pslang::ir
|
|
|
|
if (node.value)
|
|
|
|
if (node.value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto value = apply(*node.value);
|
|
|
|
auto value = apply(*node.value);
|
|
|
|
mcontext.nodes->emplace_back(return_value{value}, value->inferred_type);
|
|
|
|
module.nodes->emplace_back(return_value{value}, value->inferred_type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
mcontext.nodes->emplace_back(return_value{}, std::make_shared<types::type>(types::unit_type{}));
|
|
|
|
module.nodes->emplace_back(return_value{}, std::make_shared<types::type>(types::unit_type{}));
|
|
|
|
return last();
|
|
|
|
return last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -821,24 +821,24 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
void do_apply(ast::function_definition const & node)
|
|
|
|
void do_apply(ast::function_definition const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
auto begin = last();
|
|
|
|
auto begin = last();
|
|
|
|
|
|
|
|
|
|
|
|
lcontext.scopes.emplace_back();
|
|
|
|
lcontext.scopes.emplace_back();
|
|
|
|
for (std::size_t i = 0; i < node.arguments.size(); ++i)
|
|
|
|
for (std::size_t i = 0; i < node.arguments.size(); ++i)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
mcontext.nodes->emplace_back(argument{i}, ast::get_type(*node.arguments[i].type));
|
|
|
|
module.nodes->emplace_back(argument{i}, ast::get_type(*node.arguments[i].type));
|
|
|
|
lcontext.variables[&node.arguments[i]] = last();
|
|
|
|
lcontext.variables[&node.arguments[i]] = last();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
apply(*node.statements);
|
|
|
|
apply(*node.statements);
|
|
|
|
|
|
|
|
|
|
|
|
if (types::equal(*ast::get_type(*node.return_type), types::unit_type{}))
|
|
|
|
if (types::equal(*ast::get_type(*node.return_type), types::unit_type{}))
|
|
|
|
mcontext.nodes->emplace_back(return_value{}, std::make_shared<types::type>(types::unit_type{}));
|
|
|
|
module.nodes->emplace_back(return_value{}, std::make_shared<types::type>(types::unit_type{}));
|
|
|
|
|
|
|
|
|
|
|
|
auto end = last();
|
|
|
|
auto end = last();
|
|
|
|
|
|
|
|
|
|
|
|
lcontext.functions[&node] = {begin, end};
|
|
|
|
lcontext.functions[&node] = {begin, end};
|
|
|
|
mcontext.labels[&(*begin)] = lcontext.scopes.back().label_prefix + node.name;
|
|
|
|
module.labels[&(*begin)] = lcontext.scopes.back().label_prefix + node.name;
|
|
|
|
|
|
|
|
|
|
|
|
lcontext.scopes.pop_back();
|
|
|
|
lcontext.scopes.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -846,7 +846,7 @@ namespace pslang::ir
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
node_ref last()
|
|
|
|
node_ref last()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return std::prev(mcontext.nodes->end());
|
|
|
|
return std::prev(module.nodes->end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
@ -854,7 +854,7 @@ namespace pslang::ir
|
|
|
|
struct compile_visitor
|
|
|
|
struct compile_visitor
|
|
|
|
: ast::const_statement_visitor<compile_visitor>
|
|
|
|
: ast::const_statement_visitor<compile_visitor>
|
|
|
|
{
|
|
|
|
{
|
|
|
|
module_context & mcontext;
|
|
|
|
compiled_module & module;
|
|
|
|
local_context & lcontext;
|
|
|
|
local_context & lcontext;
|
|
|
|
|
|
|
|
|
|
|
|
using const_statement_visitor::apply;
|
|
|
|
using const_statement_visitor::apply;
|
|
|
|
@ -890,7 +890,7 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
void apply(ast::function_definition const & node)
|
|
|
|
void apply(ast::function_definition const & node)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
compile_function_visitor{{}, {}, mcontext, lcontext}.do_apply(node);
|
|
|
|
compile_function_visitor{{}, {}, module, lcontext}.do_apply(node);
|
|
|
|
std::string label_prefix;
|
|
|
|
std::string label_prefix;
|
|
|
|
if (!lcontext.scopes.empty())
|
|
|
|
if (!lcontext.scopes.empty())
|
|
|
|
label_prefix = lcontext.scopes.back().label_prefix + node.name + ".";
|
|
|
|
label_prefix = lcontext.scopes.back().label_prefix + node.name + ".";
|
|
|
|
@ -911,10 +911,10 @@ namespace pslang::ir
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void compile(module_context & mcontext, ast::statement_list_ptr statements)
|
|
|
|
void compile(compiled_module & module, semantic::module const & module_in)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (!mcontext.nodes)
|
|
|
|
if (!module.nodes)
|
|
|
|
mcontext.nodes = std::make_shared<node_list>();
|
|
|
|
module.nodes = std::make_shared<node_list>();
|
|
|
|
|
|
|
|
|
|
|
|
// Add a fake root AST function node
|
|
|
|
// Add a fake root AST function node
|
|
|
|
// for module entry point
|
|
|
|
// for module entry point
|
|
|
|
@ -928,20 +928,20 @@ namespace pslang::ir
|
|
|
|
std::make_shared<types::type>(types::unit_type{}),
|
|
|
|
std::make_shared<types::type>(types::unit_type{}),
|
|
|
|
std::make_shared<types::type>(types::function_type{{}, std::make_shared<types::type>(types::unit_type{})}),
|
|
|
|
std::make_shared<types::type>(types::function_type{{}, std::make_shared<types::type>(types::unit_type{})}),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
statements,
|
|
|
|
module_in.statements,
|
|
|
|
{},
|
|
|
|
{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
local_context lcontext;
|
|
|
|
local_context lcontext;
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.nodes->emplace_back(label{});
|
|
|
|
module.nodes->emplace_back(label{});
|
|
|
|
auto extra_label = std::prev(mcontext.nodes->end());
|
|
|
|
auto extra_label = std::prev(module.nodes->end());
|
|
|
|
compile_visitor{{}, mcontext, lcontext}.apply(*root);
|
|
|
|
compile_visitor{{}, module, lcontext}.apply(*root);
|
|
|
|
mcontext.nodes->erase(extra_label);
|
|
|
|
module.nodes->erase(extra_label);
|
|
|
|
|
|
|
|
|
|
|
|
for (auto & symbol : lcontext.functions)
|
|
|
|
for (auto & function : lcontext.functions)
|
|
|
|
symbol.second.second++;
|
|
|
|
function.second.second++;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto const & resolve : lcontext.resolve_address)
|
|
|
|
for (auto const & resolve : lcontext.resolve_address)
|
|
|
|
std::get<instruction_address>(resolve.address->instruction).target = lcontext.functions.at(resolve.target).first;
|
|
|
|
std::get<instruction_address>(resolve.address->instruction).target = lcontext.functions.at(resolve.target).first;
|
|
|
|
@ -949,10 +949,10 @@ namespace pslang::ir
|
|
|
|
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).first;
|
|
|
|
std::get<call>(resolve.call->instruction).target = lcontext.functions.at(resolve.target).first;
|
|
|
|
|
|
|
|
|
|
|
|
for (auto const & symbol : lcontext.functions)
|
|
|
|
for (auto const & function : lcontext.functions)
|
|
|
|
mcontext.symbols[symbol.first] = {.begin = symbol.second.first, .end = symbol.second.second};
|
|
|
|
module.functions[function.first] = {.begin = function.second.first, .end = function.second.second};
|
|
|
|
|
|
|
|
|
|
|
|
mcontext.entry_point = lcontext.functions.at(std::get_if<ast::function_definition>(root.get())).first;
|
|
|
|
module.entry_point = lcontext.functions.at(std::get_if<ast::function_definition>(root.get())).first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|