Implement argument passing
This commit is contained in:
parent
5cb0e18a87
commit
1e45d66359
@ -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 ")";
|
||||
|
||||
|
20
example.elna
20
example.elna
@ -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.
|
||||
|
@ -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(¶meter->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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user