Support procedure calls without arguments
This commit is contained in:
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user