From 23b6f074c7f560d701e9a1fa5713a965af3a18a3 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 2 Dec 2025 10:22:06 +0100 Subject: Merge GCC frontend into the branch --- include/elna/frontend/ast.h | 815 +++++++++++++++++++++++++++++++++++++ include/elna/frontend/dependency.h | 55 +++ include/elna/frontend/driver.h | 51 +++ include/elna/frontend/result.h | 124 ++++++ include/elna/frontend/semantic.h | 190 +++++++++ include/elna/frontend/symbol.h | 457 +++++++++++++++++++++ include/elna/gcc/elna-builtins.h | 41 ++ include/elna/gcc/elna-diagnostic.h | 46 +++ include/elna/gcc/elna-generic.h | 97 +++++ include/elna/gcc/elna-tree.h | 105 +++++ include/elna/gcc/elna1.h | 94 +++++ 11 files changed, 2075 insertions(+) create mode 100644 include/elna/frontend/ast.h create mode 100644 include/elna/frontend/dependency.h create mode 100644 include/elna/frontend/driver.h create mode 100644 include/elna/frontend/result.h create mode 100644 include/elna/frontend/semantic.h create mode 100644 include/elna/frontend/symbol.h create mode 100644 include/elna/gcc/elna-builtins.h create mode 100644 include/elna/gcc/elna-diagnostic.h create mode 100644 include/elna/gcc/elna-generic.h create mode 100644 include/elna/gcc/elna-tree.h create mode 100644 include/elna/gcc/elna1.h (limited to 'include') diff --git a/include/elna/frontend/ast.h b/include/elna/frontend/ast.h new file mode 100644 index 0000000..bbb8a36 --- /dev/null +++ b/include/elna/frontend/ast.h @@ -0,0 +1,815 @@ +/* Abstract syntax tree representation. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include +#include +#include +#include +#include +#include "elna/frontend/symbol.h" +#include "elna/frontend/result.h" + +namespace elna::frontend +{ + enum class binary_operator + { + sum, + subtraction, + multiplication, + division, + remainder, + equals, + not_equals, + less, + greater, + less_equal, + greater_equal, + disjunction, + conjunction, + exclusive_disjunction, + shift_left, + shift_right + }; + + enum class unary_operator + { + reference, + negation, + minus + }; + + class variable_declaration; + class constant_declaration; + class procedure_declaration; + class type_declaration; + class procedure_call; + class cast_expression; + class assign_statement; + class if_statement; + class import_declaration; + class while_statement; + class return_statement; + class case_statement; + class traits_expression; + class unit; + class program; + class binary_expression; + class unary_expression; + class named_type_expression; + class array_type_expression; + class pointer_type_expression; + class record_type_expression; + class union_type_expression; + class procedure_type_expression; + class enumeration_type_expression; + class variable_expression; + class array_access_expression; + class field_access_expression; + class dereference_expression; + class designator_expression; + class literal_expression; + template + class literal; + class defer_statement; + + /** + * Interface for AST visitors. + */ + struct parser_visitor + { + virtual void visit(variable_declaration *) = 0; + virtual void visit(constant_declaration *) = 0; + virtual void visit(procedure_declaration *) = 0; + virtual void visit(type_declaration *) = 0; + virtual void visit(procedure_call *) = 0; + virtual void visit(cast_expression *) = 0; + virtual void visit(traits_expression *) = 0; + virtual void visit(assign_statement *) = 0; + virtual void visit(if_statement *) = 0; + virtual void visit(import_declaration *) = 0; + virtual void visit(while_statement *) = 0; + virtual void visit(return_statement *) = 0; + virtual void visit(defer_statement *) = 0; + virtual void visit(case_statement *) = 0; + virtual void visit(unit *) = 0; + virtual void visit(program *) = 0; + virtual void visit(binary_expression *) = 0; + virtual void visit(unary_expression *) = 0; + virtual void visit(named_type_expression *) = 0; + virtual void visit(array_type_expression *) = 0; + virtual void visit(pointer_type_expression *) = 0; + virtual void visit(record_type_expression *) = 0; + virtual void visit(union_type_expression *) = 0; + virtual void visit(procedure_type_expression *) = 0; + virtual void visit(enumeration_type_expression *) = 0; + virtual void visit(variable_expression *) = 0; + virtual void visit(array_access_expression *) = 0; + virtual void visit(field_access_expression *) = 0; + virtual void visit(dereference_expression *) = 0; + virtual void visit(literal *) = 0; + virtual void visit(literal *) = 0; + virtual void visit(literal *) = 0; + virtual void visit(literal *) = 0; + virtual void visit(literal *) = 0; + virtual void visit(literal *) = 0; + virtual void visit(literal *) = 0; + }; + + /** + * Abstract visitor that doesn't visit any nodes by default. + */ + class empty_visitor : public parser_visitor + { + [[noreturn]] void not_implemented(); + + public: + [[noreturn]] virtual void visit(named_type_expression *) override; + [[noreturn]] virtual void visit(array_type_expression *) override; + [[noreturn]] virtual void visit(pointer_type_expression *) override; + [[noreturn]] virtual void visit(program *) override; + [[noreturn]] virtual void visit(type_declaration *) override; + [[noreturn]] virtual void visit(record_type_expression *) override; + [[noreturn]] virtual void visit(union_type_expression *) override; + [[noreturn]] virtual void visit(procedure_type_expression *) override; + [[noreturn]] virtual void visit(enumeration_type_expression *) override; + + [[noreturn]] virtual void visit(variable_declaration *) override; + [[noreturn]] virtual void visit(constant_declaration *) override; + [[noreturn]] virtual void visit(procedure_declaration *) override; + [[noreturn]] virtual void visit(assign_statement *) override; + [[noreturn]] virtual void visit(if_statement *) override; + [[noreturn]] virtual void visit(import_declaration *) override; + [[noreturn]] virtual void visit(while_statement *) override; + [[noreturn]] virtual void visit(return_statement *) override; + [[noreturn]] virtual void visit(defer_statement *) override; + [[noreturn]] virtual void visit(case_statement *) override; + [[noreturn]] virtual void visit(procedure_call *) override; + [[noreturn]] virtual void visit(unit *) override; + [[noreturn]] virtual void visit(cast_expression *) override; + [[noreturn]] virtual void visit(traits_expression *) override; + [[noreturn]] virtual void visit(binary_expression *) override; + [[noreturn]] virtual void visit(unary_expression *) override; + [[noreturn]] virtual void visit(variable_expression *) override; + [[noreturn]] virtual void visit(array_access_expression *) override; + [[noreturn]] virtual void visit(field_access_expression *) override; + [[noreturn]] virtual void visit(dereference_expression *) override; + [[noreturn]] virtual void visit(literal *) override; + [[noreturn]] virtual void visit(literal *) override; + [[noreturn]] virtual void visit(literal *) override; + [[noreturn]] virtual void visit(literal *) override; + [[noreturn]] virtual void visit(literal *) override; + [[noreturn]] virtual void visit(literal *) override; + [[noreturn]] virtual void visit(literal *) override; + }; + + /** + * AST node. + */ + class node + { + const struct position source_position; + + protected: + /** + * \param position Source code position. + */ + explicit node(const position position); + + public: + virtual void accept(parser_visitor *visitor) = 0; + virtual ~node() = 0; + + /** + * \return Node position in the source code. + */ + const struct position& position() const; + }; + + class statement : public virtual node + { + }; + + class expression : public virtual node + { + public: + virtual cast_expression *is_cast(); + virtual traits_expression *is_traits(); + virtual binary_expression *is_binary(); + virtual unary_expression *is_unary(); + virtual designator_expression *is_designator(); + virtual procedure_call *is_call_expression(); + virtual literal_expression *is_literal(); + }; + + /** + * Symbol definition. + */ + class declaration : public node + { + protected: + declaration(const struct position position, identifier_definition identifier); + + public: + const identifier_definition identifier; + }; + + /** + * Some type expression. + */ + class type_expression : public node + { + public: + virtual named_type_expression *is_named(); + virtual array_type_expression *is_array(); + virtual pointer_type_expression *is_pointer(); + virtual record_type_expression *is_record(); + virtual union_type_expression *is_union(); + virtual procedure_type_expression *is_procedure(); + virtual enumeration_type_expression *is_enumeration(); + + protected: + type_expression(const struct position position); + }; + + /** + * Expression refering to a type by its name. + */ + class named_type_expression : public type_expression + { + public: + const std::string name; + + named_type_expression(const struct position position, const std::string& name); + void accept(parser_visitor *visitor) override; + named_type_expression *is_named() override; + }; + + class array_type_expression : public type_expression + { + type_expression *m_base; + + public: + const std::uint32_t size; + + array_type_expression(const struct position position, + type_expression *base, const std::uint32_t size); + ~array_type_expression(); + + void accept(parser_visitor *visitor) override; + array_type_expression *is_array() override; + + type_expression& base(); + }; + + class pointer_type_expression : public type_expression + { + type_expression *m_base; + + public: + pointer_type_expression(const struct position position, type_expression *base); + ~pointer_type_expression(); + + void accept(parser_visitor *visitor) override; + pointer_type_expression *is_pointer() override; + + type_expression& base(); + }; + + using field_declaration = std::pair; + + class record_type_expression : public type_expression + { + public: + const std::vector fields; + + record_type_expression(const struct position position, std::vector&& fields); + ~record_type_expression(); + + void accept(parser_visitor *visitor) override; + record_type_expression *is_record() override; + }; + + class union_type_expression : public type_expression + { + public: + std::vector fields; + + union_type_expression(const struct position position, std::vector&& fields); + ~union_type_expression(); + + void accept(parser_visitor *visitor) override; + union_type_expression *is_union() override; + }; + + /** + * Enumeration type. + */ + class enumeration_type_expression : public type_expression + { + public: + const std::vector members; + + enumeration_type_expression(const struct position, std::vector&& members); + + void accept(parser_visitor *visitor) override; + enumeration_type_expression *is_enumeration() override; + }; + + /** + * Variable declaration. + */ + class variable_declaration : public node + { + std::shared_ptr m_variable_type; + + public: + variable_declaration(const struct position position, + std::vector&& identifier, std::shared_ptr variable_type, + expression *body = nullptr); + variable_declaration(const struct position position, + std::vector&& identifier, std::shared_ptr variable_type, + std::monostate); + + void accept(parser_visitor *visitor) override; + + bool has_initializer() const; + + const std::vector identifiers; + type_expression& variable_type(); + expression *const body{ nullptr }; + const bool is_extern{ false }; + }; + + /** + * Literal expression. + */ + class literal_expression : public expression + { + public: + literal_expression *is_literal() override; + + protected: + literal_expression(); + }; + + /** + * Constant definition. + */ + class constant_declaration : public declaration + { + expression *m_body; + + public: + constant_declaration(const struct position position, identifier_definition identifier, + expression *body); + void accept(parser_visitor *visitor) override; + + expression& body(); + + virtual ~constant_declaration() override; + }; + + /** + * Procedure type. + */ + class procedure_type_expression : public type_expression + { + public: + using return_t = return_declaration; + + const return_t return_type; + std::vector parameters; + + procedure_type_expression(const struct position position, return_t return_type = return_t()); + ~procedure_type_expression(); + + void accept(parser_visitor *visitor) override; + procedure_type_expression *is_procedure() override; + }; + + struct block + { + block(std::vector&& constants, std::vector&& variables, + std::vector&& body); + block(const block&) = delete; + block(block&& that); + + block& operator=(const block&) = delete; + block& operator=(block&& that); + + const std::vector& variables(); + const std::vector& constants(); + const std::vector& body(); + + virtual ~block(); + + private: + std::vector m_variables; + std::vector m_constants; + std::vector m_body; + + }; + + /** + * Procedure definition. + */ + class procedure_declaration : public declaration + { + procedure_type_expression *m_heading; + + public: + std::optional body; + std::vector parameter_names; + + procedure_declaration(const struct position position, identifier_definition identifier, + procedure_type_expression *heading, block&& body); + procedure_declaration(const struct position position, identifier_definition identifier, + procedure_type_expression *heading); + void accept(parser_visitor *visitor) override; + + procedure_type_expression& heading(); + + virtual ~procedure_declaration() override; + }; + + /** + * Type definition. + */ + class type_declaration : public declaration + { + type_expression *m_body; + + public: + type_declaration(const struct position position, identifier_definition identifier, + type_expression *expression); + ~type_declaration(); + + void accept(parser_visitor *visitor) override; + + type_expression& body(); + }; + + /** + * Cast expression. + */ + class cast_expression : public expression + { + type_expression *m_target; + expression *m_value; + + public: + type expression_type; + + cast_expression(const struct position position, type_expression *target, expression *value); + void accept(parser_visitor *visitor) override; + cast_expression *is_cast() override; + + type_expression& target(); + expression& value(); + + virtual ~cast_expression() override; + }; + + class traits_expression : public expression + { + public: + std::vector parameters; + const std::string name; + std::vector types; + + traits_expression(const struct position position, const std::string& name); + ~traits_expression(); + + void accept(parser_visitor *visitor) override; + traits_expression *is_traits() override; + }; + + /** + * List of statements paired with a condition. + */ + class conditional_statements + { + expression *m_prerequisite; + + public: + const std::vector statements; + + conditional_statements(expression *prerequisite, std::vector&& statements); + + expression& prerequisite(); + + virtual ~conditional_statements(); + }; + + class return_statement : public statement + { + public: + expression *m_return_expression; + + return_statement(const struct position position, expression *return_expression); + void accept(parser_visitor *visitor) override; + + expression& return_expression(); + + virtual ~return_statement() override; + }; + + struct switch_case + { + std::vector labels; + std::vector statements; + }; + + class case_statement : public statement + { + expression *m_condition; + + public: + const std::vector cases; + const std::vector *alternative; + + case_statement(const struct position position, expression *condition, + std::vector&& cases, std::vector *alternative = nullptr); + void accept(parser_visitor *visitor) override; + expression& condition(); + }; + + class designator_expression : public expression + { + public: + virtual variable_expression *is_variable(); + virtual array_access_expression *is_array_access(); + virtual field_access_expression *is_field_access(); + virtual dereference_expression *is_dereference(); + + designator_expression *is_designator() override; + void accept(parser_visitor *visitor); + ~designator_expression() = 0; + + protected: + designator_expression(); + }; + + class variable_expression : public designator_expression, public literal_expression + { + public: + const std::string name; + + variable_expression(const struct position position, const std::string& name); + void accept(parser_visitor *visitor) override; + + variable_expression *is_variable() override; + }; + + class array_access_expression : public designator_expression + { + expression *m_base; + expression *m_index; + + public: + array_access_expression(const struct position position, expression *base, expression *index); + void accept(parser_visitor *visitor) override; + + expression& base(); + expression& index(); + + array_access_expression *is_array_access() override; + + ~array_access_expression() override; + }; + + class field_access_expression : public designator_expression + { + expression *m_base; + std::string m_field; + + public: + field_access_expression(const struct position position, expression *base, + const std::string& field); + void accept(parser_visitor *visitor) override; + + expression& base(); + std::string& field(); + + field_access_expression *is_field_access() override; + + ~field_access_expression() override; + }; + + class dereference_expression : public designator_expression + { + expression *m_base; + + public: + dereference_expression(const struct position position, expression *base); + void accept(parser_visitor *visitor) override; + + expression& base(); + + dereference_expression *is_dereference() override; + + ~dereference_expression() override; + }; + + /** + * Procedure call expression. + */ + class procedure_call : public expression, public statement + { + designator_expression *m_callable; + + public: + std::vector arguments; + + procedure_call(const struct position position, designator_expression *callable); + void accept(parser_visitor *visitor) override; + virtual procedure_call *is_call_expression() override; + + designator_expression& callable(); + + virtual ~procedure_call() override; + }; + + class assign_statement : public statement + { + designator_expression *m_lvalue; + expression *m_rvalue; + + public: + /** + * \param position Source code position. + * \param lvalue Left-hand side. + * \param rvalue Assigned expression. + */ + assign_statement(const struct position position, designator_expression *lvalue, + expression *rvalue); + void accept(parser_visitor *visitor) override; + + designator_expression& lvalue(); + expression& rvalue(); + + virtual ~assign_statement() override; + }; + + /** + * If-statement. + */ + class if_statement : public statement + { + conditional_statements *m_body; + + public: + const std::vector branches; + const std::vector *alternative; + + if_statement(const struct position position, conditional_statements *body, + std::vector&& branches, + std::vector *alternative = nullptr); + void accept(parser_visitor *visitor) override; + + conditional_statements& body(); + + virtual ~if_statement() override; + }; + + /** + * Import statement. + */ + class import_declaration : public node + { + public: + const std::vector segments; + + import_declaration(const struct position position, std::vector&& segments); + void accept(parser_visitor *visitor) override; + }; + + /** + * While-statement. + */ + class while_statement : public statement + { + conditional_statements *m_body; + + public: + const std::vector branches; + + while_statement(const struct position position, conditional_statements *body, + std::vector&& branches); + void accept(parser_visitor *visitor) override; + + conditional_statements& body(); + + virtual ~while_statement() override; + }; + + class unit : public node + { + public: + std::vector imports; + std::vector constants; + std::vector types; + std::vector variables; + std::vector procedures; + + unit(const struct position position); + virtual void accept(parser_visitor *visitor) override; + + virtual ~unit() override; + }; + + class program : public unit + { + public: + std::vector body; + + program(const struct position position); + void accept(parser_visitor *visitor) override; + + virtual ~program() override; + }; + + template + class literal : public literal_expression + { + public: + T value; + + literal(const struct position position, const T& value) + : node(position), value(value) + { + } + + void accept(parser_visitor *visitor) override + { + visitor->visit(this); + } + }; + + class defer_statement : public statement + { + public: + const std::vector statements; + + defer_statement(const struct position position, std::vector&& statements); + void accept(parser_visitor *visitor) override; + + virtual ~defer_statement() override; + }; + + class binary_expression : public expression + { + expression *m_lhs; + expression *m_rhs; + binary_operator m_operator; + + public: + binary_expression(const struct position position, expression *lhs, + expression *rhs, const binary_operator operation); + + void accept(parser_visitor *visitor) override; + binary_expression *is_binary() override; + + expression& lhs(); + expression& rhs(); + binary_operator operation() const; + + virtual ~binary_expression() override; + }; + + class unary_expression : public expression + { + expression *m_operand; + unary_operator m_operator; + + public: + unary_expression(const struct position position, expression *operand, + const unary_operator operation); + + void accept(parser_visitor *visitor) override; + unary_expression *is_unary() override; + + expression& operand(); + unary_operator operation() const; + + virtual ~unary_expression() override; + }; + + const char *print_binary_operator(const binary_operator operation); +} diff --git a/include/elna/frontend/dependency.h b/include/elna/frontend/dependency.h new file mode 100644 index 0000000..f1502d1 --- /dev/null +++ b/include/elna/frontend/dependency.h @@ -0,0 +1,55 @@ +/* Dependency graph analysis. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include +#include +#include "elna/frontend/result.h" +#include "elna/frontend/ast.h" +#include "elna/frontend/symbol.h" + +namespace elna::frontend +{ + class dependency : public error_container + { + error_list m_errors; + + public: + std::unique_ptr tree; + forward_table unresolved; + + explicit dependency(const char *path); + }; + + dependency read_source(std::istream& entry_point, const char *entry_path); + std::filesystem::path build_path(const std::vector& segments); + error_list analyze_semantics(const char *path, std::unique_ptr& tree, symbol_bag bag); + + template + struct dependency_state + { + const std::shared_ptr globals; + T custom; + std::unordered_map cache; + + explicit dependency_state(T custom) + : globals(builtin_symbol_table()), custom(custom) + { + } + }; +} diff --git a/include/elna/frontend/driver.h b/include/elna/frontend/driver.h new file mode 100644 index 0000000..66ef579 --- /dev/null +++ b/include/elna/frontend/driver.h @@ -0,0 +1,51 @@ +/* Parsing driver. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include +#include "elna/frontend/ast.h" +#include "location.hh" + +namespace elna::frontend +{ + position make_position(const yy::location& location); + + class syntax_error final : public error + { + std::string message; + + public: + syntax_error(const std::string& message, + const char *input_file, const yy::location& location); + + virtual std::string what() const override; + }; + + class driver : public error_container + { + public: + std::unique_ptr tree; + + driver(const char *input_file); + }; + + constexpr char escape_invalid_char = '\xff'; + + char escape_char(char escape); + std::optional escape_string(const char *escape); +} diff --git a/include/elna/frontend/result.h b/include/elna/frontend/result.h new file mode 100644 index 0000000..7e5ed77 --- /dev/null +++ b/include/elna/frontend/result.h @@ -0,0 +1,124 @@ +/* Miscellaneous types used across stage boundaries. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace elna::frontend +{ + /** + * Position in the source text. + */ + struct position + { + /// Line. + std::size_t line = 1; + + /// Column. + std::size_t column = 1; + }; + + /** + * A compilation error consists of an error message and position. + */ + class error + { + protected: + error(const char *path, const struct position position); + + public: + const struct position position; + const char *path; + + virtual ~error() = default; + + /// Error text. + virtual std::string what() const = 0; + + /// Error line in the source text. + std::size_t line() const; + + /// Error column in the source text. + std::size_t column() const; + }; + + using error_list = typename std::deque>; + + class error_container + { + protected: + error_list m_errors; + + error_container(const char *input_file); + + public: + const char *input_file; + + error_list& errors(); + + template + void add_error(Args... arguments) + { + auto new_error = std::make_unique(arguments...); + m_errors.emplace_back(std::move(new_error)); + } + + bool has_errors() const; + }; + + /** + * Tags a procedure type as never returning. + */ + template + struct return_declaration + { + return_declaration() = default; + + explicit return_declaration(T type) + : proper_type(type) + { + } + + explicit return_declaration(std::monostate) + : no_return(true) + { + } + + T proper_type{}; + bool no_return{ false }; + }; + + struct identifier_definition + { + std::string name; + bool exported; + + bool operator==(const identifier_definition& that) const; + bool operator==(const std::string& that) const; + }; +} + +template<> +struct std::hash +{ + std::size_t operator()(const elna::frontend::identifier_definition& key) const noexcept; +}; diff --git a/include/elna/frontend/semantic.h b/include/elna/frontend/semantic.h new file mode 100644 index 0000000..8a295e4 --- /dev/null +++ b/include/elna/frontend/semantic.h @@ -0,0 +1,190 @@ +/* Name analysis. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include +#include +#include +#include + +#include "elna/frontend/ast.h" +#include "elna/frontend/result.h" +#include "elna/frontend/symbol.h" + +namespace elna::frontend +{ + class undeclared_error : public error + { + const std::string identifier; + + public: + undeclared_error(const std::string& identifier, const char *path, const struct position position); + + std::string what() const override; + }; + + class already_declared_error : public error + { + const std::string identifier; + + public: + already_declared_error(const std::string& identifier, const char *path, const struct position position); + + std::string what() const override; + }; + + class field_duplication_error : public error + { + const std::string field_name; + + public: + field_duplication_error(const std::string& field_name, const char *path, const struct position position); + + std::string what() const override; + }; + + class cyclic_declaration_error : public error + { + const std::vector cycle; + + public: + cyclic_declaration_error(const std::vector& cycle, + const char *path, const struct position position); + + std::string what() const override; + }; + + class return_error : public error + { + const std::string identifier; + + public: + return_error(const std::string& identifier, const char *path, const struct position position); + + std::string what() const override; + }; + + class variable_initializer_error : public error + { + public: + variable_initializer_error(const char *path, const struct position position); + + std::string what() const override; + }; + + /** + * Checks types. + */ + class type_analysis_visitor final : public empty_visitor, public error_container + { + bool returns; + symbol_bag bag; + + bool check_unresolved_symbol(std::shared_ptr alias, + std::vector& path); + + public: + explicit type_analysis_visitor(const char *path, symbol_bag bag); + + void visit(program *program) override; + + void visit(procedure_declaration *definition) override; + void visit(assign_statement *) override; + void visit(if_statement *) override; + void visit(while_statement *) override; + void visit(return_statement *) override; + void visit(defer_statement *) override; + void visit(case_statement *) override; + void visit(procedure_call *) override; + void visit(unit *unit) override; + void visit(type_declaration *definition) override; + }; + + /** + * Performs name analysis. + */ + class name_analysis_visitor final : public parser_visitor, public error_container + { + type current_type; + constant_info::variant current_literal; + + symbol_bag bag; + + procedure_type build_procedure(procedure_type_expression& type_expression); + std::vector build_composite_type(const std::vector& fields); + + public: + name_analysis_visitor(const char *path, symbol_bag bag); + + void visit(named_type_expression *type_expression) override; + void visit(array_type_expression *type_expression) override; + void visit(pointer_type_expression *type_expression) override; + void visit(program *program) override; + void visit(type_declaration *definition) override; + void visit(record_type_expression *type_expression) override; + void visit(union_type_expression *type_expression) override; + void visit(procedure_type_expression *type_expression) override; + void visit(enumeration_type_expression *type_expression) override; + + void visit(variable_declaration *declaration) override; + void visit(constant_declaration *definition) override; + void visit(procedure_declaration *definition) override; + void visit(assign_statement *statement) override; + void visit(if_statement *statement) override; + void visit(import_declaration *) override; + void visit(while_statement *statement) override; + void visit(return_statement *statement) override; + void visit(defer_statement *statement) override; + void visit(case_statement *statement) override; + void visit(procedure_call *call) override; + void visit(unit *unit) override; + void visit(cast_expression *expression) override; + void visit(traits_expression *trait) override; + void visit(binary_expression *expression) override; + void visit(unary_expression *expression) override; + void visit(variable_expression *) override; + void visit(array_access_expression *expression) override; + void visit(field_access_expression *expression) override; + void visit(dereference_expression *expression) override; + void visit(literal *literal) override; + void visit(literal *literal) override; + void visit(literal *literal) override; + void visit(literal *literal) override; + void visit(literal *literal) override; + void visit(literal *literal) override; + void visit(literal *literal) override; + }; + + /** + * Collects global declarations without resolving any symbols. + */ + class declaration_visitor final : public empty_visitor, public error_container + { + public: + forward_table unresolved; + + explicit declaration_visitor(const char *path); + + void visit(program *program) override; + void visit(import_declaration *) override; + void visit(unit *unit) override; + void visit(type_declaration *definition) override; + void visit(variable_declaration *declaration) override; + void visit(procedure_declaration *definition) override; + }; +} diff --git a/include/elna/frontend/symbol.h b/include/elna/frontend/symbol.h new file mode 100644 index 0000000..ec912ef --- /dev/null +++ b/include/elna/frontend/symbol.h @@ -0,0 +1,457 @@ +/* Symbol definitions. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "elna/frontend/result.h" + +namespace elna::frontend +{ + class alias_type; + class primitive_type; + class record_type; + class union_type; + class pointer_type; + class array_type; + class procedure_type; + class enumeration_type; + + class type + { + enum class type_tag + { + empty, + alias, + primitive, + record, + _union, + pointer, + array, + procedure, + enumeration + }; + type_tag tag{ type_tag::empty }; + union + { + std::weak_ptr alias; + std::shared_ptr primitive; + std::shared_ptr record; + std::shared_ptr _union; + std::shared_ptr pointer; + std::shared_ptr array; + std::shared_ptr procedure; + std::shared_ptr enumeration; + }; + + void copy(const type& other); + void move(type&& other); + + public: + type(); + explicit type(std::shared_ptr alias); + explicit type(std::shared_ptr primitive); + explicit type(std::shared_ptr record); + explicit type(std::shared_ptr _union); + explicit type(std::shared_ptr pointer); + explicit type(std::shared_ptr array); + explicit type(std::shared_ptr procedure); + explicit type(std::shared_ptr enumeration); + + type(const type& other); + type& operator=(const type& other); + + type(type&& other); + type& operator=(type&& other); + + bool operator==(const std::nullptr_t&); + + ~type(); + + template + std::shared_ptr get() const; + + bool empty() const; + }; + + struct alias_type + { + const std::string name; + type reference; + + explicit alias_type(const std::string& name); + }; + + struct pointer_type + { + const type base; + + explicit pointer_type(type base); + }; + + struct array_type + { + const type base; + const std::uint64_t size; + + array_type(type base, std::uint64_t size); + }; + + struct primitive_type + { + const std::string identifier; + + explicit primitive_type(const std::string& identifier); + }; + + using type_field = std::pair; + + struct record_type + { + std::vector fields; + }; + + struct union_type + { + std::vector fields; + }; + + struct procedure_type + { + using return_t = return_declaration; + + std::vector parameters; + const return_t return_type; + + procedure_type(return_t return_type = return_t()); + }; + + struct enumeration_type + { + std::vector members; + + explicit enumeration_type(const std::vector& members); + }; + + class type_info; + class procedure_info; + class constant_info; + class variable_info; + + class info : public std::enable_shared_from_this + { + public: + bool exported{ false }; + + virtual ~info() = 0; + + virtual std::shared_ptr is_type(); + virtual std::shared_ptr is_procedure(); + virtual std::shared_ptr is_constant(); + virtual std::shared_ptr is_variable(); + }; + + /** + * Symbol table. + */ + template + class symbol_map + { + public: + using symbol_ptr = typename std::enable_if< + std::is_convertible::value || std::is_assignable::value, + T + >::type; + using iterator = typename std::unordered_map::iterator; + using const_iterator = typename std::unordered_map::const_iterator; + + private: + std::unordered_map entries; + std::shared_ptr outer_scope; + + public: + /** + * Constructs a new symbol with an optional outer scope. + * + * \param scope Outer scope. + */ + explicit symbol_map(std::shared_ptr scope = nullptr) + : outer_scope(scope) + { + } + + iterator begin() + { + return this->entries.begin(); + } + + iterator end() + { + return this->entries.end(); + } + + const_iterator cbegin() const + { + return this->entries.cbegin(); + } + + const_iterator cend() const + { + return this->entries.cend(); + } + + /** + * \return Symbol count in the current scope. + */ + std::size_t size() const + { + return this->entries.size(); + } + + /** + * Looks for symbol in the table by name. Returns nothing if the symbol + * can not be found. + * + * \param name Symbol name. + * + * \return Symbol from the table if found. + */ + symbol_ptr lookup(const std::string& name) + { + auto entry = entries.find(name); + + if (entry != entries.cend()) + { + return entry->second; + } + if (this->outer_scope != nullptr) + { + return this->outer_scope->lookup(name); + } + return nothing; + } + + /** + * \param name Symbol name. + * + * \return Whether the table contains a symbol with the given name. + */ + bool contains(const std::string& name) + { + return lookup(name) != nothing; + } + + /** + * Registers new symbol. + * + * \param name Symbol name. + * \param entry Symbol information. + * + * \return Whether the insertion took place. + */ + bool enter(const std::string& name, symbol_ptr entry) + { + return lookup(name) == nothing && entries.insert({ name, entry }).second; + } + + /** + * Returns the outer scope or nullptr if the this is the global scope. + * + * \return Outer scope. + */ + std::shared_ptr scope() + { + return this->outer_scope; + } + }; + + using symbol_table = symbol_map, std::nullptr_t, nullptr>; + using forward_table = std::unordered_map>; + + class type_info : public info + { + public: + const type symbol; + + explicit type_info(const type symbol); + std::shared_ptr is_type() override; + }; + + /** + * Procedure symbol information. + */ + class procedure_info : public info + { + public: + /// Procedure type. + const procedure_type symbol; + + /// Parameter names. + const std::vector names; + + /// Local definitions. + std::shared_ptr scope; + + /** + * Constructs procedure symbol information. + * + * \param symbol Procedure type. + * \param names Parameter names. + * \param scope Local definition (is `nullptr` for extern symbols). + */ + procedure_info(const procedure_type symbol, const std::vector names, + std::shared_ptr scope = nullptr); + + std::shared_ptr is_procedure() override; + + /** + * \return Whether this is an extern symbol. + */ + bool is_extern() const; + }; + + class constant_info : public info + { + public: + using variant = typename + std::variant; + + const variant symbol; + + explicit constant_info(const variant& symbol); + std::shared_ptr is_constant() override; + }; + + /** + * Variable symbol information. + */ + class variable_info : public info + { + public: + /// Variable type. + const type symbol; + + /// Whether this is an extern symbol. + const bool is_extern; + + /** + * Constructs a variable symbol information. + * + * \param symbol Variable type. + * \param is_extern Whether this is an extern symbol. + */ + variable_info(const type symbol, bool is_extern); + + std::shared_ptr is_variable() override; + }; + + std::shared_ptr builtin_symbol_table(); + + /** + * Symbol bag contains: + * + * - the symbol table of a module itself + * - symbol tables of imported modules + * - forward declarations + */ + class symbol_bag + { + std::shared_ptr symbols; + std::forward_list> imports; + forward_table unresolved; + + public: + + /** + * \param unresolved Forward declarations collected in the previous step. + * \param global_table Global symbols. + */ + symbol_bag(forward_table&& unresolved, std::shared_ptr global_table); + + /** + * Looks up a symbol in the current and imported modules. + * + * \param name Symbol name to look up. + * + * \return Symbol from one of the symbol tables if found. + */ + std::shared_ptr lookup(const std::string& name); + + /** + * Inserts a symbol into the current scope. + * + * \param name Symbol name. + * \param entry Symbol info. + * + * \return Whether the insertion took place. + */ + bool enter(const std::string& name, std::shared_ptr entry); + + /** + * Enters a new scope. + * + * \return Reference to the allocated scope. + */ + std::shared_ptr enter(); + + /** + * Sets the current scope to \a child. + * + * \param child New scope. + */ + void enter(std::shared_ptr child); + + /** + * Leave the current scope. + * + * \return Left scope. + */ + std::shared_ptr leave(); + + /** + * Checks whether there is a forward declaration \a symbol_name and + * returns it if so. + * + * \param symbol_name Type name to look up. + * \return Forward declaration or `nullptr` if the symbol is not declared. + */ + std::shared_ptr declared(const std::string& symbol_name); + + /** + * Completes the forward-declared type \a symbol_name and defines it to + * be \a resolution. + * + * \param symbol_name Type name. + * \param resolution Type definition. + * \return Alias to the defined type. + */ + std::shared_ptr resolve(const std::string& symbol_name, type& resolution); + + /** + * Add imported symbols to the scope. + * + * \param bag Symbol bag of another module. + */ + void add_import(const symbol_bag& bag); + }; +} diff --git a/include/elna/gcc/elna-builtins.h b/include/elna/gcc/elna-builtins.h new file mode 100644 index 0000000..60baab7 --- /dev/null +++ b/include/elna/gcc/elna-builtins.h @@ -0,0 +1,41 @@ +/* Builtin definitions. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#include + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "tree-iterator.h" + +#include "elna/gcc/elna-tree.h" + +namespace elna::gcc +{ + void init_ttree(); + std::shared_ptr builtin_symbol_table(); + + void rewrite_symbol_table(std::shared_ptr info_table, std::shared_ptr symbols); + tree handle_symbol(const std::string& symbol_name, std::shared_ptr reference, + std::shared_ptr symbols); + tree get_inner_alias(const frontend::type& type, std::shared_ptr symbols); + void declare_procedure(const std::string& name, const frontend::procedure_info& info, + std::shared_ptr symbols); + tree declare_variable(const std::string& name, const frontend::variable_info& info, + std::shared_ptr symbols); +} diff --git a/include/elna/gcc/elna-diagnostic.h b/include/elna/gcc/elna-diagnostic.h new file mode 100644 index 0000000..83f768e --- /dev/null +++ b/include/elna/gcc/elna-diagnostic.h @@ -0,0 +1,46 @@ +/* Elna frontend specific diagnostic routines. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "input.h" +#include "tree.h" +#include "diagnostic.h" + +#include +#include + +#include "elna/frontend/result.h" + +namespace elna::gcc +{ + struct linemap_guard + { + explicit linemap_guard(const char *filename); + linemap_guard(const linemap_guard&) = delete; + linemap_guard(linemap_guard&&) = delete; + + ~linemap_guard(); + }; + + location_t get_location(const frontend::position *position); + std::string print_type(tree type); + void report_errors(const std::deque>& errors); +} diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h new file mode 100644 index 0000000..97cd512 --- /dev/null +++ b/include/elna/gcc/elna-generic.h @@ -0,0 +1,97 @@ +/* Visitor generating a GENERIC tree. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include "elna/frontend/ast.h" +#include "elna/frontend/symbol.h" +#include "elna/frontend/semantic.h" +#include "elna/gcc/elna-tree.h" + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "tree-iterator.h" + +#include +#include + +namespace elna::gcc +{ + class generic_visitor final : public frontend::empty_visitor + { + tree current_expression{ NULL_TREE }; + elna::frontend::symbol_bag bag; + std::shared_ptr symbols; + + void enter_scope(); + tree leave_scope(); + + void make_if_branch(frontend::conditional_statements& branch, tree goto_endif); + + tree build_arithmetic_operation(frontend::binary_expression *expression, + tree_code operator_code, tree left, tree right); + tree build_comparison_operation(frontend::binary_expression *expression, + tree_code operator_code, tree left, tree right); + tree build_bit_logic_operation(frontend::binary_expression *expression, tree left, tree right); + tree build_equality_operation(frontend::binary_expression *expression, tree left, tree right); + void build_procedure_call(location_t call_location, + tree procedure_address, const std::vector& arguments); + void build_record_call(location_t call_location, + tree symbol, const std::vector& arguments); + bool build_builtin_procedures(frontend::procedure_call *call); + void build_assert_builtin(location_t call_location, const std::vector& arguments); + + bool expect_trait_type_only(frontend::traits_expression *trait); + bool expect_trait_for_integral_type(frontend::traits_expression *trait); + void visit_statements(const std::vector& statements); + bool assert_constant(location_t expression_location); + + public: + generic_visitor(std::shared_ptr symbol_table, elna::frontend::symbol_bag bag); + + void visit(frontend::program *program) override; + void visit(frontend::procedure_declaration *definition) override; + void visit(frontend::procedure_call *call) override; + void visit(frontend::cast_expression *expression) override; + void visit(frontend::traits_expression *trait) override; + void visit(frontend::literal *literal) override; + void visit(frontend::literal *literal) override; + void visit(frontend::literal *literal) override; + void visit(frontend::literal *boolean) override; + void visit(frontend::literal *character) override; + void visit(frontend::literal *) override; + void visit(frontend::literal *string) override; + void visit(frontend::binary_expression *expression) override; + void visit(frontend::unary_expression *expression) override; + void visit(frontend::constant_declaration *definition) override; + void visit(frontend::variable_declaration *declaration) override; + void visit(frontend::variable_expression *expression) override; + void visit(frontend::array_access_expression *expression) override; + void visit(frontend::field_access_expression *expression) override; + void visit(frontend::dereference_expression *expression) override; + void visit(frontend::unit *unit) override; + void visit(frontend::assign_statement *statement) override; + void visit(frontend::if_statement *statement) override; + void visit(frontend::import_declaration *) override; + void visit(frontend::while_statement *statement) override; + void visit(frontend::return_statement *statement) override; + void visit(frontend::defer_statement *statement) override; + void visit(frontend::case_statement *statement) override; + }; +} diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h new file mode 100644 index 0000000..48dfeb5 --- /dev/null +++ b/include/elna/gcc/elna-tree.h @@ -0,0 +1,105 @@ +/* Utilities to manipulate GCC trees. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +#include + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "tree-iterator.h" +#include "stringpool.h" +#include "fold-const.h" + +#include "elna/frontend/ast.h" +#include "elna/frontend/symbol.h" +#include "elna/gcc/elna1.h" + +namespace elna::gcc +{ + using symbol_table = frontend::symbol_map; + + bool is_integral_type(tree type); + bool is_numeric_type(tree type); + bool is_unique_type(tree type); + bool is_void_type(tree type); + + /** + * \param type The type to evaluate. + * \return Whether this type can be converted to another type. + */ + bool is_castable_type(tree type); + + /** + * \param lhs Left hand value. + * \param rhs Right hand value. + * \return Whether rhs can be assigned to lhs. + */ + bool are_compatible_pointers(tree lhs_type, tree rhs); + + /** + * Prepares a value to be bound to a variable or parameter. + * + * If rvalue is a procedure declaration, builds a procedure pointer. + * + * \param rvalue Value to be assigned. + * \return Processed value. + */ + tree prepare_rvalue(tree rvalue); + + /** + * \param assignee Assignee. + * \param assignee Assignment. + * \return Whether an expression assignment can be assigned to a variable of type assignee. + */ + bool is_assignable_from(tree assignee, tree assignment); + + void append_statement(tree statement_tree); + void defer(tree statement_tree); + tree chain_defer(); + + tree do_pointer_arithmetic(frontend::binary_operator binary_operator, + tree left, tree right, location_t expression_location); + tree build_binary_operation(bool condition, frontend::binary_expression *expression, + tree_code operator_code, tree left, tree right, tree target_type); + tree build_arithmetic_operation(frontend::binary_expression *expression, + tree_code operator_code, tree left, tree right); + tree build_field(location_t location, tree record_type, const std::string name, tree type); + tree find_field_by_name(location_t expression_location, tree type, const std::string& field_name); + tree build_global_pointer_type(tree type); + tree build_static_array_type(tree type, const std::uint64_t size); + tree build_enumeration_type(const std::vector& members); + tree build_label_decl(const char *name, location_t loc); + + tree extract_constant(tree expression); + + template + tree call_built_in(location_t call_location, const char *name, tree return_type, Args... arguments) + { + tree *builtin = elna_global_decls->get(name); + gcc_assert(builtin != nullptr); + + tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(*builtin)); + tree builtin_addr = build1_loc(call_location, ADDR_EXPR, build_pointer_type(fndecl_type), *builtin); + + tree argument_trees[sizeof...(Args)] = {arguments...}; + + return fold_build_call_array(return_type, builtin_addr, sizeof...(Args), argument_trees); + } +} diff --git a/include/elna/gcc/elna1.h b/include/elna/gcc/elna1.h new file mode 100644 index 0000000..91d0e6f --- /dev/null +++ b/include/elna/gcc/elna1.h @@ -0,0 +1,94 @@ +/* Language-dependent hooks for Elna. + Copyright (C) 2025 Free Software Foundation, Inc. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +. */ + +#pragma once + +enum elna_tree_index +{ + ELNA_TI_INT_TYPE, + ELNA_TI_WORD_TYPE, + ELNA_TI_CHAR_TYPE, + ELNA_TI_BOOL_TYPE, + ELNA_TI_POINTER_TYPE, + ELNA_TI_FLOAT_TYPE, + ELNA_TI_STRING_TYPE, + ELNA_TI_BOOL_TRUE, + ELNA_TI_BOOL_FALSE, + ELNA_TI_POINTER_NIL, + ELNA_TI_STRING_PTR_FIELD, + ELNA_TI_STRING_LENGTH_FIELD, + ELNA_TI_MAX +}; + +extern GTY(()) tree elna_global_trees[ELNA_TI_MAX]; +extern GTY(()) hash_map *elna_global_decls; + +#define elna_int_type_node elna_global_trees[ELNA_TI_INT_TYPE] +#define elna_word_type_node elna_global_trees[ELNA_TI_WORD_TYPE] +#define elna_char_type_node elna_global_trees[ELNA_TI_CHAR_TYPE] +#define elna_bool_type_node elna_global_trees[ELNA_TI_BOOL_TYPE] +#define elna_pointer_type_node elna_global_trees[ELNA_TI_POINTER_TYPE] +#define elna_float_type_node elna_global_trees[ELNA_TI_FLOAT_TYPE] +#define elna_string_type_node elna_global_trees[ELNA_TI_STRING_TYPE] +#define elna_bool_true_node elna_global_trees[ELNA_TI_BOOL_TRUE] +#define elna_bool_false_node elna_global_trees[ELNA_TI_BOOL_FALSE] +#define elna_pointer_nil_node elna_global_trees[ELNA_TI_POINTER_NIL] +#define elna_string_ptr_field_node elna_global_trees[ELNA_TI_STRING_PTR_FIELD] +#define elna_string_length_field_node elna_global_trees[ELNA_TI_STRING_LENGTH_FIELD] + +/* Language-dependent contents of a type. */ +struct GTY (()) lang_type +{ +}; + +/* Language-dependent contents of a decl. */ +struct GTY (()) lang_decl +{ +}; + +struct GTY (()) defer_scope +{ + tree defer_block; + tree try_statements; +}; + +struct GTY ((chain_next ("%h.level_chain"))) binding_level +{ + // A block chain is needed to call defer statements beloning to each block. + tree blocks; + + // Parent level. + struct binding_level *level_chain; + + // Statements before the first defer has been seen. + tree statement_list; + + // Defer statement coupled with statements following it. + vec *defers; +}; + +struct GTY (()) language_function +{ + // Local variables and constants. + tree names; + + // Lexical scope. + struct binding_level *binding_level; +}; + +#define f_binding_level DECL_STRUCT_FUNCTION(current_function_decl)->language->binding_level +#define f_names DECL_STRUCT_FUNCTION(current_function_decl)->language->names -- cgit v1.2.3