summaryrefslogtreecommitdiff
path: root/gcc/elna-diagnostic.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/elna-diagnostic.cc')
-rw-r--r--gcc/elna-diagnostic.cc167
1 files changed, 167 insertions, 0 deletions
diff --git a/gcc/elna-diagnostic.cc b/gcc/elna-diagnostic.cc
new file mode 100644
index 0000000..162d6cb
--- /dev/null
+++ b/gcc/elna-diagnostic.cc
@@ -0,0 +1,167 @@
+/* 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
+<http://www.gnu.org/licenses/>. */
+
+#include "elna/gcc/elna-diagnostic.h"
+#include "elna/gcc/elna-tree.h"
+#include "elna/gcc/elna1.h"
+
+namespace elna::gcc
+{
+ linemap_guard::linemap_guard(const char *filename)
+ {
+ linemap_add(line_table, LC_ENTER, 0, filename, 1);
+ }
+
+ linemap_guard::~linemap_guard()
+ {
+ linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
+ }
+
+ location_t get_location(const frontend::position *position)
+ {
+ linemap_line_start(line_table, position->line, 0);
+
+ return linemap_position_for_column(line_table, position->column);
+ }
+
+ std::string print_aggregate_name(tree type, const std::string& kind_name)
+ {
+ if (TYPE_IDENTIFIER(type) == NULL_TREE)
+ {
+ return kind_name;
+ }
+ else
+ {
+ return std::string(IDENTIFIER_POINTER(TYPE_IDENTIFIER(type)));
+ }
+ }
+
+ std::string print_type(tree type)
+ {
+ gcc_assert(TYPE_P(type));
+
+ tree unqualified_type = get_qualified_type(type, TYPE_UNQUALIFIED);
+ tree_code code = TREE_CODE(type);
+
+ if (unqualified_type == elna_int_type_node)
+ {
+ return "Int";
+ }
+ else if (unqualified_type == elna_word_type_node)
+ {
+ return "Word";
+ }
+ else if (unqualified_type == elna_bool_type_node)
+ {
+ return "Bool";
+ }
+ else if (unqualified_type == elna_pointer_type_node)
+ {
+ return "Pointer";
+ }
+ else if (unqualified_type == elna_float_type_node)
+ {
+ return "Float";
+ }
+ else if (unqualified_type == elna_char_type_node)
+ {
+ return "Char";
+ }
+ else if (unqualified_type == elna_string_type_node)
+ {
+ return "String";
+ }
+ else if (is_void_type(unqualified_type)) // For procedures without a return type.
+ {
+ return "()";
+ }
+ else if (POINTER_TYPE_P(unqualified_type))
+ {
+ tree pointer_target_type = TREE_TYPE(type);
+
+ if (TREE_CODE(pointer_target_type) == FUNCTION_TYPE)
+ {
+ return print_type(pointer_target_type);
+ }
+ else
+ {
+ return std::string("^" + print_type(pointer_target_type));
+ }
+ }
+ else if (code == FUNCTION_TYPE)
+ {
+ std::string output = "proc(";
+ tree parameter_type = TYPE_ARG_TYPES(type);
+ while (TREE_VALUE(parameter_type) != void_type_node)
+ {
+ output += print_type(TREE_VALUE(parameter_type));
+ parameter_type = TREE_CHAIN(parameter_type);
+ if (TREE_VALUE(parameter_type) == void_type_node)
+ {
+ break;
+ }
+ else
+ {
+ output += ", ";
+ }
+ }
+ output += ')';
+ tree return_type = TREE_TYPE(type);
+
+ if (!is_void_type(return_type))
+ {
+ output += " -> " + print_type(return_type);
+ }
+ return output;
+ }
+ else if (code == ARRAY_TYPE)
+ {
+ return "array";
+ }
+ else if (code == RECORD_TYPE)
+ {
+ return print_aggregate_name(unqualified_type, "record");
+ }
+ else if (code == UNION_TYPE)
+ {
+ return print_aggregate_name(unqualified_type, "union");
+ }
+ else if (code == ENUMERAL_TYPE)
+ {
+ return print_aggregate_name(unqualified_type, "enumeration");
+ }
+ else
+ {
+ return "<<unknown-type>>";
+ }
+ gcc_unreachable();
+ }
+
+ void report_errors(const std::deque<std::unique_ptr<frontend::error>>& errors)
+ {
+ for (const auto& error : errors)
+ {
+ location_t gcc_location{ UNKNOWN_LOCATION };
+
+ if (error->position.line != 0 || error->position.column != 0)
+ {
+ gcc_location = elna::gcc::get_location(&error->position);
+ }
+ error_at(gcc_location, error->what().c_str());
+ }
+ }
+}