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

View File

@ -103,6 +103,22 @@ begin
writei("Test not false")
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
test_primitive();
test_string();
@ -111,5 +127,7 @@ begin
test_record();
test_const();
test_if();
test_not()
test_not();
test_param(8, 7);
test_const_char()
end.

View File

@ -87,10 +87,17 @@ namespace gcc
}
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 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);
this->current_expression = NULL_TREE;
@ -122,7 +129,7 @@ namespace gcc
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();
for (const auto& definition : program->value_definitions)
@ -133,29 +140,29 @@ namespace gcc
append_to_statement_list(return_stmt, &this->current_statements);
tree_symbol_mapping mapping = leave_scope();
BLOCK_SUPERCONTEXT(mapping.block()) = this->main_fndecl;
DECL_INITIAL(this->main_fndecl) = mapping.block();
DECL_SAVED_TREE(this->main_fndecl) = mapping.bind_expression();
DECL_EXTERNAL(this->main_fndecl) = 0;
DECL_PRESERVE_P(this->main_fndecl) = 1;
gimplify_function_tree(this->main_fndecl);
cgraph_node::finalize_function(this->main_fndecl, true);
}
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)
{
parameter_types[i] = build_type(definition->parameters().at(i)->type());
}
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->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
@ -166,6 +173,21 @@ namespace gcc
DECL_RESULT(this->main_fndecl) = resdecl;
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);
tree_symbol_mapping mapping = leave_scope();
@ -180,8 +202,6 @@ namespace gcc
gimplify_function_tree(this->main_fndecl);
cgraph_node::finalize_function(this->main_fndecl, true);
free(parameter_types);
}
void generic_visitor::enter_scope()
@ -227,9 +247,9 @@ namespace gcc
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)
@ -385,15 +405,15 @@ namespace gcc
void generic_visitor::visit(source::constant_definition *definition)
{
location_t definition_location = get_location(&definition->position());
definition->body().accept(this);
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));
if (result)
{
definition->body().accept(this);
DECL_INITIAL(definition_tree) = build_int_cst_type(integer_type_node, definition->body().number());
DECL_INITIAL(definition_tree) = this->current_expression;
TREE_CONSTANT(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<double> *literal) 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::binary_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<double> *) = 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;
};
@ -123,7 +123,7 @@ namespace source
virtual void visit(number_literal<std::int32_t> *) override;
virtual void visit(number_literal<double> *) 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;
};
@ -353,12 +353,18 @@ namespace source
virtual ~variable_declaration() override;
};
class literal : public expression
{
protected:
explicit literal(const struct position position);
};
/**
* Constant definition.
*/
class constant_definition : public definition
{
number_literal<std::int32_t> *m_body;
literal *m_body;
public:
/**
@ -367,10 +373,10 @@ namespace source
* \param body Constant value.
*/
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;
number_literal<std::int32_t>& body();
literal& body();
virtual ~constant_definition() override;
};
@ -624,13 +630,13 @@ namespace source
};
template<typename T>
class number_literal : public expression
class number_literal : public literal
{
T m_number;
public:
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
{
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
class string_literal : public literal
{
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,
number_literal<std::int32_t> *body)
literal *body)
: definition(position, identifier), m_body(body)
{
}
@ -386,7 +386,7 @@ namespace source
visitor->visit(this);
}
number_literal<std::int32_t>& constant_definition::body()
literal& constant_definition::body()
{
return *m_body;
}
@ -493,23 +493,13 @@ namespace source
}
}
char_literal::char_literal(const struct position position, const unsigned char value)
: expression(position), m_character(value)
literal::literal(const struct position position)
: 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)
: expression(position), m_string(value)
: literal(position), m_string(value)
{
}

View File

@ -74,11 +74,7 @@
%precedence THEN
%precedence ELSE
%type <elna::source::number_literal<std::int32_t> *> integer_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::literal *> literal;
%type <elna::source::constant_definition *> constant_definition;
%type <std::vector<elna::source::constant_definition *>> constant_part constant_definitions;
%type <elna::source::variable_declaration *> variable_declaration;
@ -165,26 +161,6 @@ procedure_definitions:
procedure_part:
/* no procedure definitions */ {}
| 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
{
$$ = 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),
$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:
integer_literal { $$ = $1; }
| float_literal { $$ = $1; }
| boolean_literal { $$ = $1; }
| character_literal { $$ = $1; }
| string_literal { $$ = $1; }
literal { $$ = $1; }
| designator_expression { $$ = $1; }
| LEFT_PAREN expression RIGHT_PAREN { $$ = std::move($2); }
summand:
@ -359,7 +352,7 @@ 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_declaration COMMA variable_declarations
@ -371,9 +364,9 @@ variable_declarations:
variable_part:
/* no variable declarations */ {}
| 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_definition COMMA constant_definitions