Allow calling procedures defined later
This commit is contained in:
		@@ -132,7 +132,7 @@ namespace elna::gcc
 | 
			
		||||
        for (boot::expression *const argument : arguments)
 | 
			
		||||
        {
 | 
			
		||||
            location_t argument_location = get_location(&argument->position());
 | 
			
		||||
            if (is_void_type(TREE_VALUE(current_parameter)))
 | 
			
		||||
            if (VOID_TYPE_P(TREE_VALUE(current_parameter)))
 | 
			
		||||
            {
 | 
			
		||||
                error_at(argument_location, "too many arguments, expected %i, got %lu",
 | 
			
		||||
                        list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
 | 
			
		||||
@@ -155,7 +155,7 @@ namespace elna::gcc
 | 
			
		||||
        tree stmt = fold_build_call_array_loc(call_location, TREE_TYPE(symbol_type),
 | 
			
		||||
                procedure_address, vec_safe_length(argument_trees), vec_safe_address(argument_trees));
 | 
			
		||||
 | 
			
		||||
        if (!is_void_type(TREE_VALUE(current_parameter)))
 | 
			
		||||
        if (!VOID_TYPE_P(TREE_VALUE(current_parameter)))
 | 
			
		||||
        {
 | 
			
		||||
                error_at(call_location, "too few arguments, expected %i, got %lu",
 | 
			
		||||
                        list_length(TYPE_ARG_TYPES(symbol_type)) - 1, arguments.size());
 | 
			
		||||
@@ -261,13 +261,49 @@ namespace elna::gcc
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::declare_procedure(boot::procedure_definition *const definition)
 | 
			
		||||
    {
 | 
			
		||||
        tree declaration_type = build_procedure_type(definition->heading());
 | 
			
		||||
        tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
 | 
			
		||||
        this->symbols->enter(definition->identifier, fndecl);
 | 
			
		||||
 | 
			
		||||
        if (definition->heading().return_type.no_return)
 | 
			
		||||
        {
 | 
			
		||||
            TREE_THIS_VOLATILE(fndecl) = 1;
 | 
			
		||||
        }
 | 
			
		||||
        tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, TREE_TYPE(declaration_type));
 | 
			
		||||
        DECL_CONTEXT(resdecl) = fndecl;
 | 
			
		||||
        DECL_RESULT(fndecl) = resdecl;
 | 
			
		||||
 | 
			
		||||
        tree argument_chain = NULL_TREE;
 | 
			
		||||
        function_args_iterator parameter_type;
 | 
			
		||||
        function_args_iter_init(¶meter_type, declaration_type);
 | 
			
		||||
 | 
			
		||||
        std::vector<std::string>::const_iterator parameter_name = definition->parameter_names.cbegin();
 | 
			
		||||
 | 
			
		||||
        for (std::shared_ptr<boot::type_expression> parameter : definition->heading().parameters)
 | 
			
		||||
        {
 | 
			
		||||
            tree declaration_tree = build_decl(get_location(¶meter->position()), PARM_DECL,
 | 
			
		||||
                get_identifier(parameter_name->c_str()), function_args_iter_cond(¶meter_type));
 | 
			
		||||
            DECL_CONTEXT(declaration_tree) = fndecl;
 | 
			
		||||
            DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(¶meter_type);
 | 
			
		||||
 | 
			
		||||
            argument_chain = chainon(argument_chain, declaration_tree);
 | 
			
		||||
            function_args_iter_next(¶meter_type);
 | 
			
		||||
            ++parameter_name;
 | 
			
		||||
        }
 | 
			
		||||
        DECL_ARGUMENTS(fndecl) = argument_chain;
 | 
			
		||||
        TREE_PUBLIC(fndecl) = definition->exported;
 | 
			
		||||
        TREE_ADDRESSABLE(fndecl) = 1;
 | 
			
		||||
        DECL_EXTERNAL(fndecl) = definition->body == nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::program *program)
 | 
			
		||||
    {
 | 
			
		||||
        for (boot::constant_definition *const constant : program->constants)
 | 
			
		||||
        {
 | 
			
		||||
            constant->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
        for (boot::type_definition *const type : program->types)
 | 
			
		||||
        } for (boot::type_definition *const type : program->types)
 | 
			
		||||
        {
 | 
			
		||||
            type->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
@@ -276,6 +312,10 @@ namespace elna::gcc
 | 
			
		||||
            variable->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
        for (boot::procedure_definition *const procedure : program->procedures)
 | 
			
		||||
        {
 | 
			
		||||
            declare_procedure(procedure);
 | 
			
		||||
        }
 | 
			
		||||
        for (boot::procedure_definition *const procedure : program->procedures)
 | 
			
		||||
        {
 | 
			
		||||
            procedure->accept(this);
 | 
			
		||||
        }
 | 
			
		||||
@@ -338,70 +378,34 @@ namespace elna::gcc
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::visit(boot::procedure_definition *definition)
 | 
			
		||||
    {
 | 
			
		||||
        tree declaration_type = build_procedure_type(definition->heading());
 | 
			
		||||
        tree fndecl = build_fn_decl(definition->identifier.c_str(), declaration_type);
 | 
			
		||||
        this->symbols->enter(definition->identifier, fndecl);
 | 
			
		||||
 | 
			
		||||
        if (definition->heading().return_type.no_return)
 | 
			
		||||
        if (definition->body == nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            TREE_THIS_VOLATILE(fndecl) = 1;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        if (definition->body != nullptr)
 | 
			
		||||
        tree fndecl = this->symbols->lookup(definition->identifier);
 | 
			
		||||
 | 
			
		||||
        push_struct_function(fndecl, false);
 | 
			
		||||
        DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
 | 
			
		||||
 | 
			
		||||
        enter_scope();
 | 
			
		||||
 | 
			
		||||
        tree argument_chain = DECL_ARGUMENTS(fndecl);
 | 
			
		||||
        for (; argument_chain != NULL_TREE; argument_chain = TREE_CHAIN(argument_chain))
 | 
			
		||||
        {
 | 
			
		||||
            tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, TREE_TYPE(declaration_type));
 | 
			
		||||
            DECL_CONTEXT(resdecl) = fndecl;
 | 
			
		||||
            DECL_RESULT(fndecl) = resdecl;
 | 
			
		||||
 | 
			
		||||
            push_struct_function(fndecl, false);
 | 
			
		||||
            DECL_STRUCT_FUNCTION(fndecl)->language = ggc_cleared_alloc<language_function>();
 | 
			
		||||
 | 
			
		||||
            enter_scope();
 | 
			
		||||
            this->symbols->enter(IDENTIFIER_POINTER(DECL_NAME(argument_chain)), argument_chain);
 | 
			
		||||
        }
 | 
			
		||||
        tree argument_chain = NULL_TREE;
 | 
			
		||||
        function_args_iterator parameter_type;
 | 
			
		||||
        function_args_iter_init(¶meter_type, declaration_type);
 | 
			
		||||
        definition->body->accept(this);
 | 
			
		||||
        tree mapping = leave_scope();
 | 
			
		||||
 | 
			
		||||
        std::vector<std::string>::const_iterator parameter_name = definition->parameter_names.cbegin();
 | 
			
		||||
        BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
 | 
			
		||||
        DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
 | 
			
		||||
        DECL_SAVED_TREE(fndecl) = mapping;
 | 
			
		||||
 | 
			
		||||
        for (std::shared_ptr<boot::type_expression> parameter : definition->heading().parameters)
 | 
			
		||||
        {
 | 
			
		||||
            tree declaration_tree = build_decl(get_location(¶meter->position()), PARM_DECL,
 | 
			
		||||
                get_identifier(parameter_name->c_str()), function_args_iter_cond(¶meter_type));
 | 
			
		||||
            DECL_CONTEXT(declaration_tree) = fndecl;
 | 
			
		||||
            DECL_ARG_TYPE(declaration_tree) = function_args_iter_cond(¶meter_type);
 | 
			
		||||
        DECL_PRESERVE_P(fndecl) = 1;
 | 
			
		||||
 | 
			
		||||
            if (definition->body != nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                this->symbols->enter(*parameter_name, declaration_tree);
 | 
			
		||||
            }
 | 
			
		||||
            argument_chain = chainon(argument_chain, declaration_tree);
 | 
			
		||||
            function_args_iter_next(¶meter_type);
 | 
			
		||||
            ++parameter_name;
 | 
			
		||||
        }
 | 
			
		||||
        DECL_ARGUMENTS(fndecl) = argument_chain;
 | 
			
		||||
        TREE_PUBLIC(fndecl) = definition->exported;
 | 
			
		||||
        TREE_ADDRESSABLE(fndecl) = 1;
 | 
			
		||||
 | 
			
		||||
        if (definition->body != nullptr)
 | 
			
		||||
        {
 | 
			
		||||
            definition->body->accept(this);
 | 
			
		||||
            tree mapping = leave_scope();
 | 
			
		||||
 | 
			
		||||
            BLOCK_SUPERCONTEXT(BIND_EXPR_BLOCK(mapping)) = fndecl;
 | 
			
		||||
            DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
 | 
			
		||||
            DECL_SAVED_TREE(fndecl) = mapping;
 | 
			
		||||
 | 
			
		||||
            DECL_EXTERNAL(fndecl) = 0;
 | 
			
		||||
            DECL_PRESERVE_P(fndecl) = 1;
 | 
			
		||||
 | 
			
		||||
            pop_cfun();
 | 
			
		||||
            gimplify_function_tree(fndecl);
 | 
			
		||||
            cgraph_node::finalize_function(fndecl, true);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            DECL_EXTERNAL(fndecl) = 1;
 | 
			
		||||
        }
 | 
			
		||||
        pop_cfun();
 | 
			
		||||
        gimplify_function_tree(fndecl);
 | 
			
		||||
        cgraph_node::finalize_function(fndecl, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void generic_visitor::enter_scope()
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@ namespace elna::gcc
 | 
			
		||||
        std::shared_ptr<symbol_table> symbols;
 | 
			
		||||
        std::unordered_map<std::string, tree> unresolved;
 | 
			
		||||
 | 
			
		||||
        void declare_procedure(boot::procedure_definition *const definition);
 | 
			
		||||
        tree build_label_decl(const char *name, location_t loc);
 | 
			
		||||
        tree build_procedure_type(boot::procedure_type_expression& type);
 | 
			
		||||
        void build_composite_type(const std::vector<boot::field_declaration>& fields,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user