Don't append return to void procedures

This commit is contained in:
Eugen Wissner 2025-01-13 11:55:19 +01:00
parent b45b00a3f6
commit 3bd4c3af6f
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
7 changed files with 138 additions and 46 deletions

View File

@ -79,17 +79,30 @@ begin
end; end;
proc test_if(); proc test_if();
var y: Bool; var x: Bool, y: Bool;
begin begin
x := true;
y := false; y := false;
writei(""); writei("");
if y then if x and y then
writei("Test if: True") writei("Test if: True")
else else
writei("Test if: False") writei("Test if: False")
end; end;
proc test_not();
var x: Bool;
begin
x := false;
writei("");
if not x then
writei("Test not true.")
else
writei("Test not false")
end;
begin begin
test_primitive(); test_primitive();
test_string(); test_string();
@ -97,5 +110,6 @@ begin
test_pointer(); test_pointer();
test_record(); test_record();
test_const(); test_const();
test_if() test_if();
test_not()
end. end.

View File

@ -160,16 +160,13 @@ namespace gcc
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl)); 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_CONTEXT(resdecl) = this->main_fndecl;
DECL_RESULT(this->main_fndecl) = resdecl; 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(); enter_scope();
definition->body().accept(this); definition->body().accept(this);
append_to_statement_list(return_stmt, &this->current_statements);
tree_symbol_mapping mapping = leave_scope(); 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()); 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) void generic_visitor::visit(source::binary_expression *expression)
{ {
expression->lhs().accept(this); expression->lhs().accept(this);
@ -281,31 +300,6 @@ namespace gcc
operator_code = MULT_EXPR; operator_code = MULT_EXPR;
target_type = left_type; target_type = left_type;
break; 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: case source::binary_operator::less:
operator_code = LT_EXPR; operator_code = LT_EXPR;
target_type = boolean_type_node; target_type = boolean_type_node;
@ -325,6 +319,44 @@ namespace gcc
default: default:
break; 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(operator_code != ERROR_MARK);
gcc_assert(target_type != error_mark_node); gcc_assert(target_type != error_mark_node);
@ -334,15 +366,19 @@ namespace gcc
void generic_visitor::visit(source::unary_expression *expression) void generic_visitor::visit(source::unary_expression *expression)
{ {
expression->operand().accept(this);
switch (expression->operation()) switch (expression->operation())
{ {
case source::unary_operator::reference: case source::unary_operator::reference:
expression->operand().accept(this);
this->current_expression = build1_loc(get_location(&expression->position()), ADDR_EXPR, this->current_expression = build1_loc(get_location(&expression->position()), ADDR_EXPR,
build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true), build_pointer_type_for_mode(TREE_TYPE(this->current_expression), VOIDmode, true),
this->current_expression); this->current_expression);
break; 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) 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); auto else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
append_to_statement_list(else_label_expr, &this->current_statements); append_to_statement_list(else_label_expr, &this->current_statements);

View File

@ -31,6 +31,9 @@ namespace gcc
void enter_scope(); void enter_scope();
tree_symbol_mapping leave_scope(); tree_symbol_mapping leave_scope();
void build_binarary_operation(bool condition, source::binary_expression *expression,
tree_code operator_code, tree left, tree right, tree target_type);
public: public:
generic_visitor(); generic_visitor();

View File

@ -24,12 +24,15 @@ namespace source
less, less,
greater, greater,
less_equal, less_equal,
greater_equal greater_equal,
disjunction,
conjunction
}; };
enum class unary_operator enum class unary_operator
{ {
reference reference,
negation
}; };
class variable_declaration; class variable_declaration;

View File

@ -672,6 +672,12 @@ namespace source
case 'g': case 'g':
this->m_operator = binary_operator::greater_equal; this->m_operator = binary_operator::greater_equal;
break; break;
case 'o':
this->m_operator = binary_operator::disjunction;
break;
case 'a':
this->m_operator = binary_operator::conjunction;
break;
default: default:
__builtin_unreachable(); __builtin_unreachable();
} }
@ -712,6 +718,9 @@ namespace source
case '@': case '@':
this->m_operator = unary_operator::reference; this->m_operator = unary_operator::reference;
break; break;
case '!':
this->m_operator = unary_operator::negation;
break;
default: default:
__builtin_unreachable(); __builtin_unreachable();
} }
@ -923,6 +932,10 @@ namespace source
return ">"; return ">";
case binary_operator::greater_equal: case binary_operator::greater_equal:
return ">="; return ">=";
case binary_operator::conjunction:
return "and";
case binary_operator::disjunction:
return "or";
} }
__builtin_unreachable(); __builtin_unreachable();
}; };

View File

@ -79,6 +79,15 @@ true {
false { false {
return yy::parser::make_BOOLEAN(false, this->location); return yy::parser::make_BOOLEAN(false, this->location);
} }
and {
return yy::parser::make_AND(this->location);
}
or {
return yy::parser::make_OR(this->location);
}
not {
return yy::parser::make_NOT(this->location);
}
[A-Za-z_][A-Za-z0-9_]* { [A-Za-z_][A-Za-z0-9_]* {
return yy::parser::make_IDENTIFIER(yytext, this->location); return yy::parser::make_IDENTIFIER(yytext, this->location);
} }

View File

@ -66,6 +66,7 @@
%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD %token CONST VAR PROCEDURE ARRAY OF TYPE RECORD
%token BEGIN_BLOCK END_BLOCK %token BEGIN_BLOCK END_BLOCK
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
%token AND OR NOT
%token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS %token GREATER_EQUAL LESS_EQUAL LESS_THAN GREATER_THAN NOT_EQUAL EQUALS
%token PLUS MINUS MULTIPLICATION DIVISION %token PLUS MINUS MULTIPLICATION DIVISION
%token ASSIGNMENT COLON HAT AT %token ASSIGNMENT COLON HAT AT
@ -84,7 +85,7 @@
%type <std::vector<elna::source::variable_declaration *>> variable_declarations variable_part %type <std::vector<elna::source::variable_declaration *>> variable_declarations variable_part
formal_parameter_list; formal_parameter_list;
%type <elna::source::type_expression *> type_expression; %type <elna::source::type_expression *> type_expression;
%type <elna::source::expression *> expression pointer summand factor comparand; %type <elna::source::expression *> expression pointer summand factor comparand logical_operand;
%type <std::vector<elna::source::expression *>> expressions actual_parameter_list; %type <std::vector<elna::source::expression *>> expressions actual_parameter_list;
%type <elna::source::designator_expression *> designator_expression; %type <elna::source::designator_expression *> designator_expression;
%type <elna::source::compound_statement *> compound_statement; %type <elna::source::compound_statement *> compound_statement;
@ -239,6 +240,10 @@ factor:
{ {
$$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, '@'); $$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, '@');
} }
| NOT pointer
{
$$ = new elna::source::unary_expression(elna::source::make_position(@1), $2, '!');
}
| pointer { $$ = $1; } | pointer { $$ = $1; }
comparand: comparand:
summand PLUS summand summand PLUS summand
@ -250,7 +255,7 @@ comparand:
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '-'); $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '-');
} }
| summand { $$ = std::move($1); } | summand { $$ = std::move($1); }
expression: logical_operand:
comparand EQUALS comparand comparand EQUALS comparand
{ {
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '='); $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '=');
@ -265,20 +270,27 @@ expression:
} }
| comparand GREATER_THAN comparand | comparand GREATER_THAN comparand
{ {
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '>');
$1, $3, '>');
} }
| comparand LESS_EQUAL comparand | comparand LESS_EQUAL comparand
{ {
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '<');
$1, $3, '<');
} }
| comparand GREATER_EQUAL comparand | comparand GREATER_EQUAL comparand
{ {
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, '>');
$1, $3, '>');
} }
| comparand { $$ = std::move($1); } | comparand { $$ = $1; }
expression:
logical_operand AND logical_operand
{
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, 'a');
}
| logical_operand OR logical_operand
{
$$ = new elna::source::binary_expression(elna::source::make_position(@1), $1, $3, 'o');
}
| logical_operand { $$ = $1; }
expressions: expressions:
expression COMMA expressions expression COMMA expressions
{ {