diff --git a/gcc/elna-generic.cc b/gcc/elna-generic.cc index 07117cb..1783a24 100644 --- a/gcc/elna-generic.cc +++ b/gcc/elna-generic.cc @@ -1,5 +1,4 @@ #include "elna/gcc/elna-generic.h" -#include "elna/gcc/elna-tree.h" #include "elna/gcc/elna-diagnostic.h" #include "input.h" @@ -93,18 +92,16 @@ namespace gcc build_int_cst_type(integer_type_node, 0)); tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result); - this->current_statements = alloc_stmt_list(); - - empty_visitor::visit(program); + enter_scope(); + empty_visitor::visit(program); append_to_statement_list(return_stmt, &this->current_statements); + + tree_symbol_mapping mapping = leave_scope(); - tree new_block = build_block(NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); - tree bind_expr = build3(BIND_EXPR, void_type_node, NULL_TREE, this->current_statements, new_block); - - BLOCK_SUPERCONTEXT(new_block) = this->main_fndecl; - DECL_INITIAL(this->main_fndecl) = new_block; - DECL_SAVED_TREE(this->main_fndecl) = bind_expr; + 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; @@ -114,6 +111,22 @@ namespace gcc cgraph_node::finalize_function(this->main_fndecl, true); } + void generic_visitor::enter_scope() + { + this->current_statements = alloc_stmt_list(); + this->variable_chain = tree_chain(); + } + + tree_symbol_mapping generic_visitor::leave_scope() + { + tree new_block = build_block(variable_chain.head(), + NULL_TREE, NULL_TREE, NULL_TREE); + tree bind_expr = build3(BIND_EXPR, void_type_node, variable_chain.head(), + this->current_statements, new_block); + + return tree_symbol_mapping{ bind_expr, new_block }; + } + void generic_visitor::visit(source::number_literal *literal) { this->current_expression = build_int_cst_type(integer_type_node, literal->number()); @@ -304,9 +317,11 @@ namespace gcc get_identifier(declaration->identifier().c_str()), declaration_type); auto result = this->symbol_map.insert({ declaration->identifier(), declaration_tree }); - // DECL_CONTEXT(declaration_tree) = this->main_fndecl; if (result.second) { + DECL_CONTEXT(declaration_tree) = this->main_fndecl; + variable_chain.append(declaration_tree); + auto declaration_statement = build1_loc(declaration_location, DECL_EXPR, void_type_node, declaration_tree); append_to_statement_list(declaration_statement, &this->current_statements); diff --git a/gcc/elna-tree.cc b/gcc/elna-tree.cc index 210a1df..ccdabe9 100644 --- a/gcc/elna-tree.cc +++ b/gcc/elna-tree.cc @@ -22,5 +22,45 @@ namespace gcc return TREE_CODE(type) == POINTER_TYPE && TYPE_MAIN_VARIANT(TREE_TYPE(type)) == char_type_node; } + + tree tree_chain_base::head() + { + return first; + } + + void tree_chain_base::append(tree t) + { + gcc_assert(t != NULL_TREE); + + if (this->first == NULL_TREE) + { + this->first = this->last = t; + } + else + { + chain(t); + this->last = t; + } + } + + void tree_chain::chain(tree t) + { + TREE_CHAIN(this->last) = t; + } + + tree_symbol_mapping::tree_symbol_mapping(tree bind_expression, tree block) + : m_bind_expression(bind_expression), m_block(block) + { + } + + tree tree_symbol_mapping::bind_expression() + { + return m_bind_expression; + } + + tree tree_symbol_mapping::block() + { + return m_block; + } } } diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 6649251..1fb335b 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -1,6 +1,7 @@ #pragma once #include "elna/source/ast.h" +#include "elna/gcc/elna-tree.h" #include "config.h" #include "system.h" @@ -21,8 +22,12 @@ namespace gcc tree current_expression{ NULL_TREE }; std::unordered_map symbol_map; tree main_fndecl{ NULL_TREE }; + tree_chain variable_chain; - tree build_label_decl (const char *name, location_t loc); + tree build_label_decl(const char *name, location_t loc); + + void enter_scope(); + tree_symbol_mapping leave_scope(); public: void visit(source::program *program) override; diff --git a/include/elna/gcc/elna-tree.h b/include/elna/gcc/elna-tree.h index 73bb402..bc39de6 100644 --- a/include/elna/gcc/elna-tree.h +++ b/include/elna/gcc/elna-tree.h @@ -23,5 +23,36 @@ namespace gcc { void init_ttree(); bool is_string_type(tree type); + + class tree_chain_base + { + protected: + tree first{}; + tree last{}; + + public: + tree head(); + void append(tree t); + + protected: + virtual void chain(tree t) = 0; + }; + + class tree_chain final : public tree_chain_base + { + void chain(tree t) override; + }; + + class tree_symbol_mapping final + { + tree m_bind_expression; + tree m_block; + + public: + tree_symbol_mapping(tree bind_expression, tree block); + + tree bind_expression(); + tree block(); + }; } }