Don't append return to void procedures

This commit is contained in:
2025-01-13 11:55:19 +01:00
parent b45b00a3f6
commit 3bd4c3af6f
7 changed files with 138 additions and 46 deletions

View File

@ -160,16 +160,13 @@ namespace gcc
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL,
NULL_TREE, TREE_TYPE(TREE_TYPE(this->main_fndecl)));
DECL_CONTEXT(resdecl) = this->main_fndecl;
DECL_RESULT(this->main_fndecl) = resdecl;
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
build_int_cst_type(integer_type_node, 0));
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
enter_scope();
definition->body().accept(this);
append_to_statement_list(return_stmt, &this->current_statements);
tree_symbol_mapping mapping = leave_scope();
@ -240,6 +237,28 @@ namespace gcc
this->current_expression = build_string_literal(string->string().size() + 1, string->string().c_str());
}
void generic_visitor::build_binarary_operation(bool condition, source::binary_expression *expression,
tree_code operator_code, tree left, tree right, tree target_type)
{
auto expression_location = get_location(&expression->position());
auto left_type = TREE_TYPE(left);
auto right_type = TREE_TYPE(right);
if (condition)
{
this->current_expression = build2_loc(expression_location,
operator_code, target_type, left, right);
}
else
{
error_at(expression_location,
"invalid operands of type %s and %s for operator %s",
print_type(left_type), print_type(right_type),
elna::source::print_binary_operator(expression->operation()));
this->current_expression = error_mark_node;
}
}
void generic_visitor::visit(source::binary_expression *expression)
{
expression->lhs().accept(this);
@ -281,31 +300,6 @@ namespace gcc
operator_code = MULT_EXPR;
target_type = left_type;
break;
default:
break;
}
if (operator_code != ERROR_MARK) // An arithmetic operation.
{
if (target_type != integer_type_node && target_type != double_type_node)
{
error_at(expression_location,
"invalid operands of type %s and %s for operator %s",
print_type(left_type), print_type(right_type),
elna::source::print_binary_operator(expression->operation()));
this->current_expression = error_mark_node;
return;
}
}
switch (expression->operation())
{
case source::binary_operator::equals:
operator_code = EQ_EXPR;
target_type = boolean_type_node;
break;
case source::binary_operator::not_equals:
operator_code = NE_EXPR;
target_type = boolean_type_node;
break;
case source::binary_operator::less:
operator_code = LT_EXPR;
target_type = boolean_type_node;
@ -325,6 +319,44 @@ namespace gcc
default:
break;
}
if (operator_code != ERROR_MARK) // An arithmetic operation.
{
build_binarary_operation(left_type == integer_type_node || left_type == double_type_node,
expression, operator_code, left, right, target_type);
return;
}
switch (expression->operation())
{
case source::binary_operator::conjunction:
operator_code = TRUTH_ANDIF_EXPR;
target_type = boolean_type_node;
break;
case source::binary_operator::disjunction:
operator_code = TRUTH_ORIF_EXPR;
target_type = boolean_type_node;
break;
default:
break;
}
if (operator_code != ERROR_MARK) // A logical operation.
{
build_binarary_operation(left_type == boolean_type_node,
expression, operator_code, left, right, target_type);
return;
}
switch (expression->operation())
{
case source::binary_operator::equals:
operator_code = EQ_EXPR;
target_type = boolean_type_node;
break;
case source::binary_operator::not_equals:
operator_code = NE_EXPR;
target_type = boolean_type_node;
break;
default:
break;
}
gcc_assert(operator_code != ERROR_MARK);
gcc_assert(target_type != error_mark_node);
@ -334,15 +366,19 @@ namespace gcc
void generic_visitor::visit(source::unary_expression *expression)
{
expression->operand().accept(this);
switch (expression->operation())
{
case source::unary_operator::reference:
expression->operand().accept(this);
this->current_expression = build1_loc(get_location(&expression->position()), ADDR_EXPR,
build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true),
this->current_expression);
break;
case source::unary_operator::negation:
this->current_expression = build1_loc(get_location(&expression->position()), TRUTH_NOT_EXPR,
boolean_type_node, this->current_expression);
break;
}
}
@ -674,6 +710,8 @@ namespace gcc
if (statement->alternative() != nullptr)
{
append_to_statement_list(goto_endif, &this->current_statements);
auto else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
append_to_statement_list(else_label_expr, &this->current_statements);