Support procedure calls without arguments

This commit is contained in:
2024-03-26 23:04:20 +01:00
parent f2a20c2825
commit 44e32760ca
13 changed files with 317 additions and 113 deletions

View File

@ -165,13 +165,16 @@ namespace elna::riscv
void generate_intrinsics();
void relocate(std::string_view name, address_t target);
void prologue();
void epilogue(const std::size_t stack_size);
public:
std::uint32_t variable_counter = 1;
std::vector<reference> references;
std::shared_ptr<source::symbol_table> table;
visitor(std::shared_ptr<source::writer> writer);
visitor(std::shared_ptr<source::writer> writer,
std::shared_ptr<source::symbol_table> table);
virtual void visit(source::declaration *declaration) override;
virtual void visit(source::constant_definition *definition) override;

View File

@ -99,5 +99,6 @@ namespace elna::riscv
*/
std::ptrdiff_t lookup(ELFIO::symbol_section_accessor symbol_accessor, const std::string& label);
void riscv32_elf(source::program *ast, const std::filesystem::path& out_file);
void riscv32_elf(source::program *ast, std::shared_ptr<source::symbol_table> table,
const std::filesystem::path& out_file);
}

View File

@ -88,12 +88,14 @@ namespace elna::source
class declaration : public node
{
std::string m_identifier;
std::string m_type;
public:
declaration(const std::string& identifier);
declaration(const std::string& identifier, const std::string& type);
virtual void accept(parser_visitor *visitor) override;
std::string& identifier() noexcept;
std::string& type() noexcept;
};
/**
@ -124,25 +126,27 @@ namespace elna::source
class procedure_definition : public definition
{
std::unique_ptr<block> m_body;
std::vector<std::unique_ptr<declaration>> m_parameters;
public:
procedure_definition(const std::string& identifier, std::unique_ptr<block>&& body);
virtual void accept(parser_visitor *visitor) override;
block& body();
std::vector<std::unique_ptr<declaration>>& parameters() noexcept;
};
class call_statement : public statement
{
std::string m_name;
std::unique_ptr<expression> m_body;
std::vector<std::unique_ptr<expression>> m_arguments;
public:
call_statement(const std::string& name, std::unique_ptr<expression>&& body);
call_statement(const std::string& name);
virtual void accept(parser_visitor *visitor) override;
std::string& name() noexcept;
expression& arguments();
std::vector<std::unique_ptr<expression>>& arguments() noexcept;
};
class compound_statement : public statement
@ -201,7 +205,6 @@ namespace elna::source
std::unique_ptr<statement> m_body;
std::vector<std::unique_ptr<definition>> m_definitions;
std::vector<std::unique_ptr<declaration>> m_declarations;
std::shared_ptr<symbol_table> m_table;
public:
block(std::vector<std::unique_ptr<definition>>&& definitions,
@ -212,7 +215,6 @@ namespace elna::source
statement& body();
std::vector<std::unique_ptr<definition>>& definitions() noexcept;
std::vector<std::unique_ptr<declaration>>& declarations() noexcept;
std::shared_ptr<symbol_table> table();
};
class program : public block

View File

@ -8,6 +8,7 @@
#include <string>
#include <type_traits>
#include <unordered_map>
#include <vector>
namespace elna::source
{
@ -110,6 +111,32 @@ namespace elna::source
std::string what() const override;
};
class symbol_table;
/**
* Type representation.
*/
struct type
{
const std::size_t byte_size;
protected:
explicit type(const std::size_t byte_size);
};
/**
* Built-in type representation.
*/
struct primitive_type : public type
{
const std::string type_name;
primitive_type(const std::string& type_name, const std::size_t byte_size);
};
inline const primitive_type boolean_type{ "Boolean", 1 };
inline const primitive_type int_type{ "Int", 4 };
/**
* Generic language entity information.
*/
@ -122,6 +149,19 @@ namespace elna::source
info();
};
/**
* Type information.
*/
class type_info final : public info
{
class type m_type;
public:
explicit type_info(const class type& type);
~type_info() override;
const class type& type() const noexcept;
};
/**
* Constant information.
*/
@ -145,18 +185,36 @@ namespace elna::source
~variable_info() override;
};
/**
* Procedure parameter information.
*/
class parameter_info final : public info
{
class type m_type;
public:
explicit parameter_info(const class type& type);
~parameter_info() override;
const class type& type() const noexcept;
};
/**
* Procedure information.
*/
class procedure_info final : public info
{
std::size_t local_stack_size{ 0 };
std::shared_ptr<symbol_table> local_table;
public:
std::vector<parameter_info> parameter_infos;
explicit procedure_info(std::shared_ptr<symbol_table> outer_scope);
~procedure_info() override;
void stack_size(const std::size_t size) noexcept;
std::size_t stack_size() const noexcept;
std::shared_ptr<symbol_table> scope();
};
/**
@ -174,12 +232,39 @@ namespace elna::source
class symbol_table
{
std::unordered_map<std::string, std::shared_ptr<info>> entries;
std::shared_ptr<symbol_table> outer_scope;
public:
symbol_table();
/**
* Constructs a new symbol with an optional outer scope.
*
* \param scope Outer scope.
*/
explicit symbol_table(std::shared_ptr<symbol_table> scope = nullptr);
/**
* Looks for symbol in the table by name. Returns nullptr if the symbol
* can not be found.
*
* \param name Symbol name.
* \return Symbol from the table if found.
*/
std::shared_ptr<info> lookup(const std::string& name);
/**
* Registers new symbol.
*
* \param name Symbol name.
* \param entry Symbol information.
*/
void enter(const std::string& name, std::shared_ptr<info> entry);
/**
* Returns the outer scope or nullptr if the this is the global scope.
*
* \return Outer scope.
*/
std::shared_ptr<symbol_table> scope();
};
struct writer

View File

@ -6,21 +6,28 @@ namespace elna::source
{
class name_analysis_visitor final : public empty_visitor
{
std::shared_ptr<symbol_table> table;
std::shared_ptr<symbol_table> table = std::make_shared<symbol_table>();
public:
name_analysis_visitor(std::shared_ptr<symbol_table> table);
void visit(constant_definition *definition) override;
void visit(declaration *declaration) override;
void visit(block *block) override;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
};
class allocator_visitor final : public empty_visitor
{
std::ptrdiff_t offset;
std::shared_ptr<symbol_table> table;
public:
allocator_visitor(std::shared_ptr<symbol_table> table);
void visit(declaration *declaration) override;
void visit(block *block) override;
void visit(program *program) override;
void visit(procedure_definition *procedure) override;
};
class type_analysis_visitor final : public empty_visitor