aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-builtins.cc5
-rw-r--r--gcc/gcc/elna-generic.cc73
2 files changed, 56 insertions, 22 deletions
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 23315e5..637e37a 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -335,8 +335,9 @@ namespace elna::gcc
function_args_iter_next(&parameter_type);
}
DECL_ARGUMENTS(fndecl) = argument_chain;
- // Elna has no exceptions.
- TREE_NOTHROW(fndecl) = 1;
+ // Elna has no exceptions, but an extern procedure is defined elsewhere
+ // and may well be able to unwind.
+ TREE_NOTHROW(fndecl) = static_cast<unsigned>(!info.is_extern());
DECL_EXTERNAL(fndecl) = static_cast<unsigned>(info.is_extern());
// An extern procedure has C linkage whether or not Elna re-exports the name.
TREE_PUBLIC(fndecl) = static_cast<unsigned>(info.exported || info.is_extern());
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index b527280..9bb1e89 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -259,38 +259,71 @@ namespace elna::gcc
}
if (unit->entry_point.has_value())
{
- tree declaration_type = build_function_type_list(elna_int_type_node,
- elna_int_type_node,
- build_pointer_type(build_pointer_type(unsigned_intQI_type_node)),
- NULL_TREE);
- tree fndecl = build_fn_decl("main", declaration_type);
-
- tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
+ const std::shared_ptr<boot::procedure_info> entry_point = this->bag.lookup("")->is_procedure();
+ const location_t location = get_location(&entry_point->position.value());
+ tree declaration_type = unit->parameters.empty()
+ ? build_function_type_list(integer_type_node, NULL_TREE)
+ : build_function_type_list(integer_type_node,
+ integer_type_node,
+ build_pointer_type(build_pointer_type(char_type_node)),
+ NULL_TREE);
+ // build_fn_decl would mark the declaration artificial, which drops the
+ // source coordinates from the debug information.
+ tree fndecl = build_decl(location, FUNCTION_DECL, get_identifier("main"), declaration_type);
+ TREE_PUBLIC(fndecl) = 1;
+ // Elna has no exceptions.
+ TREE_NOTHROW(fndecl) = 1;
+
+ tree resdecl = build_decl(location, RESULT_DECL, NULL_TREE, integer_type_node);
DECL_CONTEXT(resdecl) = fndecl;
DECL_RESULT(fndecl) = resdecl;
begin_function(fndecl);
+ this->bag.enter(entry_point->scope);
- tree parameter_type = TYPE_ARG_TYPES(declaration_type);
- for (const char *argument_name : std::array<const char *, 2>{ "count", "parameters" })
+ if (!unit->parameters.empty())
{
- tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
- get_identifier(argument_name), TREE_VALUE(parameter_type));
- DECL_CONTEXT(declaration_tree) = fndecl;
- DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
-
- this->symbols->enter(argument_name, declaration_tree);
- DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
- parameter_type = TREE_CHAIN(parameter_type);
+ constexpr std::array<const char *, 2> argument_names{ "$argc", "$argv" };
+ std::array<tree, argument_names.size()> argument_declarations{};
+ tree parameter_type = TYPE_ARG_TYPES(declaration_type);
+
+ for (std::size_t i = 0; i < argument_names.size(); ++i)
+ {
+ tree declaration_tree = build_decl(UNKNOWN_LOCATION, PARM_DECL,
+ get_identifier(argument_names.at(i)), TREE_VALUE(parameter_type));
+ DECL_CONTEXT(declaration_tree) = fndecl;
+ DECL_ARG_TYPE(declaration_tree) = TREE_VALUE(parameter_type);
+ DECL_ARTIFICIAL(declaration_tree) = 1;
+
+ DECL_ARGUMENTS(fndecl) = chainon(DECL_ARGUMENTS(fndecl), declaration_tree);
+ argument_declarations.at(i) = declaration_tree;
+ parameter_type = TREE_CHAIN(parameter_type);
+ }
+ const boot::type& argument_type = entry_point->symbol.parameters.front();
+ tree slice_type = get_inner_alias(argument_type, this->symbols);
+ tree ptr_field = TYPE_FIELDS(slice_type);
+ tree length_field = TREE_CHAIN(ptr_field);
+ tree slice_pointer = fold_convert(TREE_TYPE(ptr_field), argument_declarations.at(1));
+ tree slice_length = fold_convert(TREE_TYPE(length_field), argument_declarations.at(0));
+ tree slice = build_slice(slice_type, slice_pointer, slice_length);
+ const boot::variable_info argument_info(argument_type, false);
+
+ declare_local_variable(unit->parameters.front(), argument_info, slice);
+ }
+ for (boot::variable_declaration *const variable : unit->entry_point->variables)
+ {
+ variable->accept(this);
}
visit_statements(unit->entry_point->statements);
- tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl),
- integer_zero_node);
+
+ unit->entry_point->return_expression->accept(this);
+ tree return_value = fold_convert(integer_type_node, this->current_expression);
+ tree set_result = build2(INIT_EXPR, void_type_node, DECL_RESULT(fndecl), return_value);
tree return_stmt = build1(RETURN_EXPR, void_type_node, set_result);
append_statement(return_stmt);
this->current_expression = NULL_TREE;
- DECL_EXTERNAL(fndecl) = 0;
+ this->bag.leave();
finish_function(fndecl);
}
}