Implement argument passing

This commit is contained in:
Eugen Wissner 2025-01-15 01:48:09 +01:00
parent 5cb0e18a87
commit 1e45d66359
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
7 changed files with 106 additions and 92 deletions

View File

@ -28,6 +28,8 @@ integer = digit { digit };
float = integer "." integer; float = integer "." integer;
boolean = "true" | "false"; boolean = "true" | "false";
literal = integer | float | boolean | "'" character "'" | """ { character } """;
program = [ "type" type_definitions ";" ] program = [ "type" type_definitions ";" ]
[ constant_part ] [ constant_part ]
{ procedure_definition } { procedure_definition }
@ -64,11 +66,7 @@ comparand = summand { ("+" | "-") summand };
summand = factor { ("*" | "/") factor }; summand = factor { ("*" | "/") factor };
factor = pointer { unary_prefix pointer }; factor = pointer { unary_prefix pointer };
pointer = integer pointer = literal
| float
| boolean
| "'" character "'"
| """ { character } """
| designator_expression { $$ = $1; } | designator_expression { $$ = $1; }
| "(" expression ")"; | "(" expression ")";

View File

@ -103,6 +103,22 @@ begin
writei("Test not false") writei("Test not false")
end; end;
proc test_param(d: Int, e: Int);
begin
writei("");
writei("Test param");
writei(d);
writei(e)
end;
proc test_const_char();
const x = 'u';
begin
writei("");
writei("Test constant character");
writei(x)
end;
begin begin
test_primitive(); test_primitive();
test_string(); test_string();
@ -111,5 +127,7 @@ begin
test_record(); test_record();
test_const(); test_const();
test_if(); test_if();
test_not() test_not();
test_param(8, 7);
test_const_char()
end. end.

View File

@ -87,10 +87,17 @@ namespace gcc
} }
else if (symbol) else if (symbol)
{ {
tree fndecl_type = build_function_type_list(integer_type_node, NULL_TREE); tree fndecl_type = build_function_type(void_type_node, TYPE_ARG_TYPES(symbol->payload));
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload); tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
tree stmt = build_call_nary(integer_type_node, printf_fn, 0); std::vector<tree> arguments(statement->arguments().size());
for (std::size_t i = 0; i < statement->arguments().size(); ++i)
{
statement->arguments().at(i)->accept(this);
arguments[i] = this->current_expression;
}
tree stmt = build_call_array_loc(get_location(&statement->position()),
void_type_node, printf_fn, arguments.size(), arguments.data());
append_to_statement_list(stmt, &this->current_statements); append_to_statement_list(stmt, &this->current_statements);
this->current_expression = NULL_TREE; this->current_expression = NULL_TREE;
@ -122,7 +129,7 @@ namespace gcc
tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl), tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(main_fndecl),
build_int_cst_type(integer_type_node, 0)); build_int_cst_type(integer_type_node, 0));
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
enter_scope(); enter_scope();
for (const auto& definition : program->value_definitions) for (const auto& definition : program->value_definitions)
@ -133,29 +140,29 @@ namespace gcc
append_to_statement_list(return_stmt, &this->current_statements); append_to_statement_list(return_stmt, &this->current_statements);
tree_symbol_mapping mapping = leave_scope(); tree_symbol_mapping mapping = leave_scope();
BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl; BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl;
DECL_INITIAL(this->main_fndecl) = mapping.block(); DECL_INITIAL(this->main_fndecl) = mapping.block();
DECL_SAVED_TREE(this->main_fndecl) = mapping.bind_expression(); DECL_SAVED_TREE(this->main_fndecl) = mapping.bind_expression();
DECL_EXTERNAL(this->main_fndecl) = 0; DECL_EXTERNAL(this->main_fndecl) = 0;
DECL_PRESERVE_P(this->main_fndecl) = 1; DECL_PRESERVE_P(this->main_fndecl) = 1;
gimplify_function_tree(this->main_fndecl); gimplify_function_tree(this->main_fndecl);
cgraph_node::finalize_function(this->main_fndecl, true); cgraph_node::finalize_function(this->main_fndecl, true);
} }
void generic_visitor::visit(source::procedure_definition *definition) void generic_visitor::visit(source::procedure_definition *definition)
{ {
tree *parameter_types = reinterpret_cast<tree *>(xmalloc(definition->parameters().size() * sizeof(tree))); std::vector<tree> parameter_types(definition->parameters().size());
for (std::size_t i = 0; i < definition->parameters().size(); ++i) for (std::size_t i = 0; i < definition->parameters().size(); ++i)
{ {
parameter_types[i] = build_type(definition->parameters().at(i)->type()); parameter_types[i] = build_type(definition->parameters().at(i)->type());
} }
tree declaration_type = build_function_type_array(void_type_node, tree declaration_type = build_function_type_array(void_type_node,
definition->parameters().size(), parameter_types); definition->parameters().size(), parameter_types.data());
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type); this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl)); this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
@ -166,6 +173,21 @@ namespace gcc
DECL_RESULT(this->main_fndecl) = resdecl; DECL_RESULT(this->main_fndecl) = resdecl;
enter_scope(); enter_scope();
gcc::tree_chain argument_chain;
for (std::size_t i = 0; i < definition->parameters().size(); ++i)
{
auto parameter = definition->parameters().at(i);
tree declaration_tree = build_decl(get_location(&parameter->position()), PARM_DECL,
get_identifier(parameter->identifier().c_str()), parameter_types[i]);
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
DECL_ARG_TYPE(declaration_tree) = parameter_types[i];
this->symbol_map->enter(parameter->identifier(), source::make_info(declaration_tree));
argument_chain.append(declaration_tree);
}
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
definition->body().accept(this); definition->body().accept(this);
tree_symbol_mapping mapping = leave_scope(); tree_symbol_mapping mapping = leave_scope();
@ -180,8 +202,6 @@ namespace gcc
gimplify_function_tree(this->main_fndecl); gimplify_function_tree(this->main_fndecl);
cgraph_node::finalize_function(this->main_fndecl, true); cgraph_node::finalize_function(this->main_fndecl, true);
free(parameter_types);
} }
void generic_visitor::enter_scope() void generic_visitor::enter_scope()
@ -227,9 +247,9 @@ namespace gcc
this->current_expression = build_int_cst_type(boolean_type_node, boolean->number()); this->current_expression = build_int_cst_type(boolean_type_node, boolean->number());
} }
void generic_visitor::visit(source::char_literal *character) void generic_visitor::visit(source::number_literal<unsigned char> *character)
{ {
this->current_expression = build_int_cstu(elna_char_type_node, character->character()); this->current_expression = build_int_cstu(elna_char_type_node, character->number());
} }
void generic_visitor::visit(source::string_literal *string) void generic_visitor::visit(source::string_literal *string)
@ -385,15 +405,15 @@ namespace gcc
void generic_visitor::visit(source::constant_definition *definition) void generic_visitor::visit(source::constant_definition *definition)
{ {
location_t definition_location = get_location(&definition->position()); location_t definition_location = get_location(&definition->position());
definition->body().accept(this);
tree definition_tree = build_decl(definition_location, CONST_DECL, tree definition_tree = build_decl(definition_location, CONST_DECL,
get_identifier(definition->identifier().c_str()), integer_type_node); get_identifier(definition->identifier().c_str()), TREE_TYPE(this->current_expression));
auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree)); auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree));
if (result) if (result)
{ {
definition->body().accept(this); DECL_INITIAL(definition_tree) = this->current_expression;
DECL_INITIAL(definition_tree) = build_int_cst_type(integer_type_node, definition->body().number());
TREE_CONSTANT(definition_tree) = 1; TREE_CONSTANT(definition_tree) = 1;
TREE_READONLY(definition_tree) = 1; TREE_READONLY(definition_tree) = 1;

View File

@ -43,7 +43,7 @@ namespace gcc
void visit(source::number_literal<std::int32_t> *literal) override; void visit(source::number_literal<std::int32_t> *literal) override;
void visit(source::number_literal<double> *literal) override; void visit(source::number_literal<double> *literal) override;
void visit(source::number_literal<bool> *boolean) override; void visit(source::number_literal<bool> *boolean) override;
void visit(source::char_literal *character) override; void visit(source::number_literal<unsigned char> *character) override;
void visit(source::string_literal *string) override; void visit(source::string_literal *string) override;
void visit(source::binary_expression *expression) override; void visit(source::binary_expression *expression) override;
void visit(source::unary_expression *expression) override; void visit(source::unary_expression *expression) override;

View File

@ -90,7 +90,7 @@ namespace source
virtual void visit(number_literal<std::int32_t> *) = 0; virtual void visit(number_literal<std::int32_t> *) = 0;
virtual void visit(number_literal<double> *) = 0; virtual void visit(number_literal<double> *) = 0;
virtual void visit(number_literal<bool> *) = 0; virtual void visit(number_literal<bool> *) = 0;
virtual void visit(char_literal *) = 0; virtual void visit(number_literal<unsigned char> *) = 0;
virtual void visit(string_literal *) = 0; virtual void visit(string_literal *) = 0;
}; };
@ -123,7 +123,7 @@ namespace source
virtual void visit(number_literal<std::int32_t> *) override; virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<double> *) override; virtual void visit(number_literal<double> *) override;
virtual void visit(number_literal<bool> *) override; virtual void visit(number_literal<bool> *) override;
virtual void visit(char_literal *) override; virtual void visit(number_literal<unsigned char> *) override;
virtual void visit(string_literal *) override; virtual void visit(string_literal *) override;
}; };
@ -353,12 +353,18 @@ namespace source
virtual ~variable_declaration() override; virtual ~variable_declaration() override;
}; };
class literal : public expression
{
protected:
explicit literal(const struct position position);
};
/** /**
* Constant definition. * Constant definition.
*/ */
class constant_definition : public definition class constant_definition : public definition
{ {
number_literal<std::int32_t> *m_body; literal *m_body;
public: public:
/** /**
@ -367,10 +373,10 @@ namespace source
* \param body Constant value. * \param body Constant value.
*/ */
constant_definition(const struct position position, const std::string& identifier, constant_definition(const struct position position, const std::string& identifier,
number_literal<std::int32_t> *body); literal *body);
virtual void accept(parser_visitor *visitor) override; virtual void accept(parser_visitor *visitor) override;
number_literal<std::int32_t>& body(); literal& body();
virtual ~constant_definition() override; virtual ~constant_definition() override;
}; };
@ -624,13 +630,13 @@ namespace source
}; };
template<typename T> template<typename T>
class number_literal : public expression class number_literal : public literal
{ {
T m_number; T m_number;
public: public:
number_literal(const struct position position, const T value) number_literal(const struct position position, const T value)
: expression(position), m_number(value) : literal(position), m_number(value)
{ {
} }
@ -645,18 +651,7 @@ namespace source
} }
}; };
class char_literal : public expression class string_literal : public literal
{
unsigned char m_character;
public:
char_literal(const struct position position, const unsigned char value);
virtual void accept(parser_visitor *visitor) override;
unsigned char character() const;
};
class string_literal : public expression
{ {
std::string m_string; std::string m_string;

View File

@ -146,7 +146,7 @@ namespace source
{ {
} }
void empty_visitor::visit(char_literal *) void empty_visitor::visit(number_literal<unsigned char> *)
{ {
} }
@ -376,7 +376,7 @@ namespace source
} }
constant_definition::constant_definition(const struct position position, const std::string& identifier, constant_definition::constant_definition(const struct position position, const std::string& identifier,
number_literal<std::int32_t> *body) literal *body)
: definition(position, identifier), m_body(body) : definition(position, identifier), m_body(body)
{ {
} }
@ -386,7 +386,7 @@ namespace source
visitor->visit(this); visitor->visit(this);
} }
number_literal<std::int32_t>& constant_definition::body() literal& constant_definition::body()
{ {
return *m_body; return *m_body;
} }
@ -493,23 +493,13 @@ namespace source
} }
} }
char_literal::char_literal(const struct position position, const unsigned char value) literal::literal(const struct position position)
: expression(position), m_character(value) : expression(position)
{ {
} }
void char_literal::accept(parser_visitor *visitor)
{
visitor->visit(this);
}
unsigned char char_literal::character() const
{
return m_character;
}
string_literal::string_literal(const struct position position, const std::string& value) string_literal::string_literal(const struct position position, const std::string& value)
: expression(position), m_string(value) : literal(position), m_string(value)
{ {
} }

View File

@ -74,11 +74,7 @@
%precedence THEN %precedence THEN
%precedence ELSE %precedence ELSE
%type <elna::source::number_literal<std::int32_t> *> integer_literal; %type <elna::source::literal *> literal;
%type <elna::source::number_literal<double> *> float_literal;
%type <elna::source::number_literal<bool> *> boolean_literal;
%type <elna::source::char_literal *> character_literal;
%type <elna::source::string_literal *> string_literal;
%type <elna::source::constant_definition *> constant_definition; %type <elna::source::constant_definition *> constant_definition;
%type <std::vector<elna::source::constant_definition *>> constant_part constant_definitions; %type <std::vector<elna::source::constant_definition *>> constant_part constant_definitions;
%type <elna::source::variable_declaration *> variable_declaration; %type <elna::source::variable_declaration *> variable_declaration;
@ -165,26 +161,6 @@ procedure_definitions:
procedure_part: procedure_part:
/* no procedure definitions */ {} /* no procedure definitions */ {}
| procedure_definitions { std::swap($$, $1); } | procedure_definitions { std::swap($$, $1); }
integer_literal: INTEGER
{
$$ = new elna::source::number_literal<std::int32_t>(elna::source::make_position(@1), $1);
};
float_literal: FLOAT
{
$$ = new elna::source::number_literal<double>(elna::source::make_position(@1), $1);
};
character_literal: CHARACTER
{
$$ = new elna::source::char_literal(elna::source::make_position(@1), $1.at(0));
};
string_literal: STRING
{
$$ = new elna::source::string_literal(elna::source::make_position(@1), $1);
};
boolean_literal: BOOLEAN
{
$$ = new elna::source::number_literal<bool>(elna::source::make_position(@1), $1);
};
compound_statement: BEGIN_BLOCK optional_statements END_BLOCK compound_statement: BEGIN_BLOCK optional_statements END_BLOCK
{ {
$$ = new elna::source::compound_statement(elna::source::make_position(@1)); $$ = new elna::source::compound_statement(elna::source::make_position(@1));
@ -215,12 +191,29 @@ if_statement:
$$ = new elna::source::if_statement(elna::source::make_position(@1), $$ = new elna::source::if_statement(elna::source::make_position(@1),
$2, $4, $6); $2, $4, $6);
} }
literal:
INTEGER
{
$$ = new elna::source::number_literal<std::int32_t>(elna::source::make_position(@1), $1);
}
| FLOAT
{
$$ = new elna::source::number_literal<double>(elna::source::make_position(@1), $1);
}
| BOOLEAN
{
$$ = new elna::source::number_literal<bool>(elna::source::make_position(@1), $1);
}
| CHARACTER
{
$$ = new elna::source::number_literal<unsigned char>(elna::source::make_position(@1), $1.at(0));
}
| STRING
{
$$ = new elna::source::string_literal(elna::source::make_position(@1), $1);
}
pointer: pointer:
integer_literal { $$ = $1; } literal { $$ = $1; }
| float_literal { $$ = $1; }
| boolean_literal { $$ = $1; }
| character_literal { $$ = $1; }
| string_literal { $$ = $1; }
| designator_expression { $$ = $1; } | designator_expression { $$ = $1; }
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); } | LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
summand: summand:
@ -359,7 +352,7 @@ type_expression:
} }
variable_declaration: IDENTIFIER COLON type_expression variable_declaration: IDENTIFIER COLON type_expression
{ {
$$ = new elna::source::variable_declaration(elna::source::make_position(@1), $1, $3); $$ = new elna::source::variable_declaration(elna::source::make_position(@1), $1, $3);
}; };
variable_declarations: variable_declarations:
variable_declaration COMMA variable_declarations variable_declaration COMMA variable_declarations
@ -371,9 +364,9 @@ variable_declarations:
variable_part: variable_part:
/* no variable declarations */ {} /* no variable declarations */ {}
| VAR variable_declarations SEMICOLON { std::swap($$, $2); } | VAR variable_declarations SEMICOLON { std::swap($$, $2); }
constant_definition: IDENTIFIER EQUALS integer_literal constant_definition: IDENTIFIER EQUALS literal
{ {
$$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3); $$ = new elna::source::constant_definition(elna::source::make_position(@1), $1, $3);
} }
constant_definitions: constant_definitions:
constant_definition COMMA constant_definitions constant_definition COMMA constant_definitions