aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-builtins.cc19
-rw-r--r--gcc/gcc/elna-generic.cc72
-rw-r--r--gcc/gcc/elna-module-loader.cc8
-rw-r--r--gcc/gcc/elna-tree.cc39
4 files changed, 63 insertions, 75 deletions
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 18dcc52..23315e5 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -16,6 +16,7 @@ along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#include "elna/gcc/elna-builtins.h"
+#include "elna/gcc/elna-diagnostic.h"
#include "elna/gcc/elna1.h"
#include "stor-layout.h"
#include "stringpool.h"
@@ -304,7 +305,11 @@ namespace elna::gcc
const std::shared_ptr<symbol_table>& symbols)
{
tree declaration_type = gcc::build_procedure_type(info.symbol, symbols);
- tree fndecl = build_fn_decl(name.c_str(), declaration_type);
+ const location_t location = info.position.has_value()
+ ? get_location(&info.position.value())
+ : UNKNOWN_LOCATION;
+ tree fndecl = build_decl(location, FUNCTION_DECL,
+ get_identifier(name.c_str()), declaration_type);
symbols->enter(name, fndecl);
if (info.symbol.return_type.no_return)
@@ -330,8 +335,11 @@ namespace elna::gcc
function_args_iter_next(&parameter_type);
}
DECL_ARGUMENTS(fndecl) = argument_chain;
+ // Elna has no exceptions.
+ TREE_NOTHROW(fndecl) = 1;
DECL_EXTERNAL(fndecl) = static_cast<unsigned>(info.is_extern());
- TREE_PUBLIC(fndecl) = static_cast<unsigned>(info.exported);
+ // 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());
}
tree declare_variable(const std::string& name, const boot::variable_info& info,
@@ -361,7 +369,7 @@ namespace elna::gcc
}
void rewrite_symbol_table(const std::shared_ptr<boot::symbol_table>& info_table,
- const std::shared_ptr<symbol_table>& symbols)
+ const std::shared_ptr<symbol_table>& symbols, const bool imported)
{
for (auto& [symbol_name, symbol_info] : *info_table)
{
@@ -371,7 +379,10 @@ namespace elna::gcc
}
else if (auto variable_info = symbol_info->is_variable())
{
- declare_variable(symbol_name, *variable_info, symbols);
+ tree declaration_tree = declare_variable(symbol_name, *variable_info, symbols);
+
+ DECL_EXTERNAL(declaration_tree) =
+ static_cast<unsigned>(imported || variable_info->is_extern);
}
else if (auto procedure_info = symbol_info->is_procedure())
{
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index e2d50b4..fb68136 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -176,8 +176,7 @@ namespace elna::gcc
for (const boot::field_initializer& initializer : expression->field_initializers)
{
- tree field_decl = find_field_by_name(get_location(&expression->position()),
- record_type, initializer.name());
+ tree field_decl = find_field_by_name(record_type, initializer.name());
initializer.value().accept(this);
// NOLINTNEXTLINE(misc-const-correctness)
CONSTRUCTOR_APPEND_ELT(tree_arguments, field_decl, this->current_expression);
@@ -474,8 +473,6 @@ namespace elna::gcc
DECL_INITIAL(fndecl) = BIND_EXPR_BLOCK(mapping);
DECL_SAVED_TREE(fndecl) = mapping;
- DECL_PRESERVE_P(fndecl) = 1;
-
dump_function(TDI_original, fndecl);
pop_cfun();
@@ -720,8 +717,7 @@ namespace elna::gcc
if (lang_hooks.decls.global_bindings_p())
{
- TREE_STATIC(declaration_tree) =
- static_cast<unsigned>(!variable_identifier.exported() && !declaration->is_extern);
+ TREE_STATIC(declaration_tree) = static_cast<unsigned>(!declaration->is_extern);
varpool_node::get_create(declaration_tree);
varpool_node::finalize_decl(declaration_tree);
}
@@ -741,14 +737,9 @@ namespace elna::gcc
{
tree symbol = this->symbols->lookup(expression->name);
- if (symbol == NULL_TREE)
- {
- this->current_expression = error_mark_node;
- }
- else
- {
- this->current_expression = symbol;
- }
+ // Name analysis rejects an undeclared name.
+ gcc_assert(symbol != NULL_TREE);
+ this->current_expression = symbol;
}
void generic_visitor::visit(boot::array_access_expression *expression)
@@ -813,15 +804,12 @@ namespace elna::gcc
}
else
{
- tree field_declaration = find_field_by_name(expression_location,
+ tree field_declaration = find_field_by_name(
TREE_TYPE(this->current_expression), expression->field().name());
- if (field_declaration != error_mark_node)
- {
- this->current_expression = build3_loc(expression_location, COMPONENT_REF,
- TREE_TYPE(field_declaration), this->current_expression,
- field_declaration, NULL_TREE);
- }
+ this->current_expression = build3_loc(expression_location, COMPONENT_REF,
+ TREE_TYPE(field_declaration), this->current_expression,
+ field_declaration, NULL_TREE);
}
}
@@ -866,10 +854,7 @@ namespace elna::gcc
}
result = make_if_branch(statement->branch(), result);
- if (result != error_mark_node)
- {
- append_statement(result);
- }
+ append_statement(result);
this->current_expression = NULL_TREE;
}
@@ -1010,16 +995,13 @@ namespace elna::gcc
}
result = make_if_branch(statement->branch(), result, goto_check);
- if (result != error_mark_node)
- {
- tree check_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
- void_type_node, while_check_label);
- tree end_label_expr = build1(LABEL_EXPR, void_type_node, while_end_label);
+ tree check_label_expr = build1_loc(prerequisite_location, LABEL_EXPR,
+ void_type_node, while_check_label);
+ tree end_label_expr = build1(LABEL_EXPR, void_type_node, while_end_label);
- append_statement(check_label_expr);
- append_statement(result);
- append_statement(end_label_expr);
- }
+ append_statement(check_label_expr);
+ append_statement(result);
+ append_statement(end_label_expr);
this->current_expression = NULL_TREE;
}
@@ -1077,7 +1059,7 @@ namespace elna::gcc
case_label->accept(this);
const location_t case_location = get_location(&case_label->position());
- assert_constant(case_location);
+ assert_constant();
tree case_label_declaration = create_artificial_label(case_location);
tree case_expression = build_case_label(this->current_expression, NULL_TREE, case_label_declaration);
@@ -1130,10 +1112,7 @@ namespace elna::gcc
for (boot::expression *const case_label : case_block.labels)
{
case_label->accept(this);
- if (!assert_constant(get_location(&case_label->position())))
- {
- continue;
- }
+ assert_constant();
tree label_comparison = build_equality_comparison(get_location(&case_label->position()),
condition_value, this->current_expression,
statement->condition().type_decoration, EQ_EXPR);
@@ -1153,19 +1132,12 @@ namespace elna::gcc
}
}
- bool generic_visitor::assert_constant(location_t expression_location)
+ void generic_visitor::assert_constant()
{
tree constant_expression = extract_constant(this->current_expression);
- if (constant_expression == NULL_TREE)
- {
- error_at(expression_location, "Expected a constant expression");
- this->current_expression = error_mark_node;
- }
- else
- {
- this->current_expression = constant_expression;
- }
- return this->current_expression != error_mark_node;
+ // Type checking rejects a case label that is not a constant expression.
+ gcc_assert(constant_expression != NULL_TREE);
+ this->current_expression = constant_expression;
}
}
diff --git a/gcc/gcc/elna-module-loader.cc b/gcc/gcc/elna-module-loader.cc
index 8827a1e..5852bbe 100644
--- a/gcc/gcc/elna-module-loader.cc
+++ b/gcc/gcc/elna-module-loader.cc
@@ -78,9 +78,9 @@ namespace elna::gcc
}
void module_loader::finalize(const std::filesystem::path&,
- const std::shared_ptr<boot::symbol_table>& module_scope) const
+ const std::shared_ptr<boot::symbol_table>& module_scope, const bool imported) const
{
- rewrite_symbol_table(module_scope, this->symbols);
+ rewrite_symbol_table(module_scope, this->symbols, imported);
}
void compile_files(const char *const *filenames, unsigned int count)
@@ -99,9 +99,9 @@ namespace elna::gcc
report_errors(diagnostics);
}
- if (result.value != nullptr)
+ if (result.value != nullptr && result.errors.empty())
{
- linemap_add(line_table, LC_ENTER, 0, key.native().c_str(), 1);
+ linemap_add(line_table, LC_ENTER, 0, ggc_strdup(key.native().c_str()), 1);
generic_visitor visitor{ state.custom, state.find(key)->second, target };
result.value->accept(&visitor);
linemap_add(line_table, LC_LEAVE, 0, nullptr, 0);
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index cddb407..7aa4012 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -97,6 +97,14 @@ namespace elna::gcc
return field_declaration;
}
+ // The generic Pointer has no pointee size; it advances byte by byte.
+ static tree pointer_stride(tree pointer_type, tree offset_type)
+ {
+ return pointer_type == elna_pointer_type_node
+ ? size_one_node
+ : fold_convert(offset_type, size_in_bytes(TREE_TYPE(pointer_type)));
+ }
+
tree do_pointer_arithmetic(boot::binary_operator binary_operator,
tree left, tree right, location_t operation_location)
{
@@ -124,9 +132,7 @@ namespace elna::gcc
{
return error_mark_node;
}
- tree size_exp = pointer_type == elna_pointer_type_node
- ? size_one_node
- : fold_convert(TREE_TYPE(offset), size_in_bytes(TREE_TYPE(TREE_TYPE(pointer))));
+ tree size_exp = pointer_stride(pointer_type, TREE_TYPE(offset));
offset = fold_build2(MULT_EXPR, TREE_TYPE(offset), offset, size_exp);
offset = fold_convert(size_type_node, offset);
@@ -139,7 +145,7 @@ namespace elna::gcc
{
tree pointer_type = left_type;
tree offset_type = right_type;
- tree size_exp = fold_convert(offset_type, size_in_bytes(TREE_TYPE(pointer_type)));
+ tree size_exp = pointer_stride(pointer_type, offset_type);
tree convert_expression = fold_build2(MULT_EXPR, offset_type, right, size_exp);
convert_expression = fold_convert(size_type_node, convert_expression);
@@ -156,13 +162,11 @@ namespace elna::gcc
gcc_unreachable();
}
- tree find_field_by_name(location_t, tree type, const std::string& field_name)
+ tree find_field_by_name(tree type, const std::string& field_name)
{
- // NOLINTNEXTLINE(readability-simplify-boolean-expr)
- if (type == error_mark_node || !RECORD_OR_UNION_TYPE_P(type))
- {
- return error_mark_node;
- }
+ // Name analysis rejects a field the record does not have.
+ gcc_assert(RECORD_OR_UNION_TYPE_P(type));
+
for (tree field = TYPE_FIELDS(type); field != NULL_TREE; field = TREE_CHAIN(field))
{
if (field_name == IDENTIFIER_POINTER(DECL_NAME(field)))
@@ -170,7 +174,7 @@ namespace elna::gcc
return field;
}
}
- return error_mark_node;
+ gcc_unreachable();
}
tree build_static_array_type(tree type, const std::uint64_t size)
@@ -233,8 +237,13 @@ namespace elna::gcc
tree extract_constant(tree expression)
{
const int code = TREE_CODE(expression);
+ // A mutable variable can have a constant initializer too, so readonly is
+ // what marks one whose value is known at compile time.
+ const bool constant_variable = code == VAR_DECL && TREE_READONLY(expression)
+ && DECL_INITIAL(expression) != NULL_TREE
+ && TREE_CONSTANT(DECL_INITIAL(expression));
- if (code == CONST_DECL)
+ if (code == CONST_DECL || constant_variable)
{
return DECL_INITIAL(expression);
}
@@ -333,11 +342,7 @@ namespace elna::gcc
for (const auto& [field_name, field_value] : fields)
{
- tree field_decl = find_field_by_name(UNKNOWN_LOCATION, type, field_name);
- if (field_decl == error_mark_node)
- {
- return NULL_TREE;
- }
+ tree field_decl = find_field_by_name(type, field_name);
tree value_tree = constant_to_tree(field_value, symbols, TREE_TYPE(field_decl));
if (value_tree == NULL_TREE)
{