aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-07-25 23:33:22 +0200
committerEugen Wissner <belka@caraus.de>2026-07-26 02:45:19 +0200
commitdea1c177cd3592cc24fd15ad446a676da2e4da28 (patch)
treeca29eefe25858ca49d376614ecf6ddda9e144299 /gcc
parent4f89a02e03b056d0c55108a8c9194126ef4ee811 (diff)
downloadelna-dea1c177cd3592cc24fd15ad446a676da2e4da28.tar.gz
Support #offset trait at compile time
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/elna-builtins.cc82
-rw-r--r--gcc/gcc/elna-diagnostic.cc6
-rw-r--r--gcc/gcc/elna-generic.cc321
-rw-r--r--gcc/gcc/elna-tree.cc41
-rw-r--r--gcc/gcc/elna1.cc27
5 files changed, 257 insertions, 220 deletions
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 6ea8874..226de4a 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -15,8 +15,6 @@ 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 <algorithm>
-
#include "elna/gcc/elna-builtins.h"
#include "elna/gcc/elna1.h"
#include "stor-layout.h"
@@ -41,7 +39,7 @@ namespace elna::gcc
}
static
- tree declare_builtin_type(std::shared_ptr<symbol_table> symbol_table, const char *name, tree type)
+ tree declare_builtin_type(const std::shared_ptr<symbol_table>& symbol_table, const char *name, tree type)
{
tree identifier = get_identifier(name);
tree type_declaration = build_decl(UNKNOWN_LOCATION, TYPE_DECL, identifier, type);
@@ -65,21 +63,44 @@ namespace elna::gcc
return builtin_table;
}
- tree build_composite_type(const boot::ordered_map<boot::type>& fields,
- tree composite_type_node, std::shared_ptr<symbol_table> symbols)
+ static tree build_composite_type(const boot::ordered_map<boot::type>& fields,
+ tree composite_type_node, const std::shared_ptr<symbol_table>& symbols)
{
- for (auto& field : fields)
+ for (const auto& field : fields)
{
tree rewritten_field = get_inner_alias(field.second, symbols);
tree field_declaration = build_field(UNKNOWN_LOCATION,
composite_type_node, field.first, rewritten_field);
TYPE_FIELDS(composite_type_node) = chainon(TYPE_FIELDS(composite_type_node), field_declaration);
}
- layout_type(composite_type_node);
return composite_type_node;
}
- tree build_procedure_type(const boot::procedure_type& procedure, std::shared_ptr<symbol_table> symbols)
+ static bool layout_record_type(tree record_type, const std::shared_ptr<boot::record_type>& subject)
+ {
+ layout_type(record_type);
+ const auto& target = get_host_target();
+ auto record_layout = boot::layout_record(subject, target);
+
+ if (!record_layout.has_value())
+ {
+ return false;
+ }
+ for (tree field = TYPE_FIELDS(record_type); field != NULL_TREE; field = TREE_CHAIN(field))
+ {
+ std::string field_name(IDENTIFIER_POINTER(DECL_NAME(field)));
+
+ DECL_FIELD_OFFSET(field) = size_int(record_layout.value().offset_map.find(field_name)->second);
+ DECL_FIELD_BIT_OFFSET(field) = bitsize_zero_node;
+ }
+ TYPE_SIZE_UNIT(record_type) = size_int(record_layout.value().size);
+ TYPE_SIZE(record_type) = bitsize_int(record_layout.value().size * BITS_PER_UNIT);
+
+ return true;
+ }
+
+ static tree build_procedure_type(const boot::procedure_type& procedure,
+ const std::shared_ptr<symbol_table>& symbols)
{
std::vector<tree> parameter_types(procedure.parameters.size());
@@ -93,14 +114,15 @@ namespace elna::gcc
{
return_type = get_inner_alias(procedure.return_type.proper_type, symbols);
}
- return build_function_type_array(return_type, procedure.parameters.size(), parameter_types.data());
+ return build_function_type_array(return_type,
+ static_cast<int>(procedure.parameters.size()), parameter_types.data());
}
- tree get_inner_alias(const boot::type& type, std::shared_ptr<symbol_table> symbols)
+ tree get_inner_alias(const boot::type& type, const std::shared_ptr<symbol_table>& symbols)
{
if (auto reference = type.get<boot::primitive_type>())
{
- auto looked_up = symbols->lookup(reference->identifier);
+ tree looked_up = symbols->lookup(reference->identifier);
gcc_assert(looked_up != NULL_TREE);
return TREE_TYPE(looked_up);
@@ -122,7 +144,10 @@ namespace elna::gcc
}
}
build_composite_type(reference->fields, composite_type_node, symbols);
-
+ if (!layout_record_type(composite_type_node, reference))
+ {
+ return error_mark_node;
+ }
return composite_type_node;
}
else if (auto reference = type.get<boot::enumeration_type>())
@@ -154,7 +179,7 @@ namespace elna::gcc
}
else if (auto reference = type.get<boot::procedure_type>())
{
- auto procedure = build_procedure_type(*reference, symbols);
+ tree procedure = build_procedure_type(*reference, symbols);
return build_pointer_type(procedure);
}
@@ -170,14 +195,19 @@ namespace elna::gcc
return error_mark_node;
}
- tree handle_symbol(const std::string& symbol_name, std::shared_ptr<boot::alias_type> reference,
- std::shared_ptr<symbol_table> symbols)
+ tree handle_symbol(const std::string& symbol_name,
+ const std::shared_ptr<boot::alias_type>& reference,
+ const std::shared_ptr<symbol_table>& symbols)
{
tree looked_up = symbols->lookup(symbol_name);
if (looked_up == NULL_TREE)
{
tree type_tree = get_inner_alias(reference->referent, symbols);
+ if (type_tree == error_mark_node)
+ {
+ return error_mark_node;
+ }
looked_up = build_decl(UNKNOWN_LOCATION, TYPE_DECL,
get_identifier(symbol_name.c_str()), type_tree);
@@ -197,7 +227,7 @@ namespace elna::gcc
}
void declare_procedure(const std::string& name, const boot::procedure_info& info,
- std::shared_ptr<symbol_table> symbols)
+ 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);
@@ -230,37 +260,39 @@ namespace elna::gcc
}
DECL_ARGUMENTS(fndecl) = argument_chain;
TREE_ADDRESSABLE(fndecl) = 1;
- DECL_EXTERNAL(fndecl) = info.is_extern();
- TREE_PUBLIC(fndecl) = info.exported;
+ DECL_EXTERNAL(fndecl) = static_cast<unsigned>(info.is_extern());
+ TREE_PUBLIC(fndecl) = static_cast<unsigned>(info.exported);
}
tree declare_variable(const std::string& name, const boot::variable_info& info,
- std::shared_ptr<symbol_table> symbols)
+ const std::shared_ptr<symbol_table>& symbols)
{
- auto *variable_type = get_inner_alias(info.symbol, symbols);
+ tree variable_type = get_inner_alias(info.symbol, symbols);
tree declaration_tree = build_decl(UNKNOWN_LOCATION, VAR_DECL, get_identifier(name.c_str()), variable_type);
TREE_ADDRESSABLE(declaration_tree) = 1;
- DECL_EXTERNAL(declaration_tree) = info.is_extern;
- TREE_PUBLIC(declaration_tree) = info.exported;
+ DECL_EXTERNAL(declaration_tree) = static_cast<unsigned>(info.is_extern);
+ TREE_PUBLIC(declaration_tree) = static_cast<unsigned>(info.exported);
symbols->enter(name, declaration_tree);
return declaration_tree;
}
- void declare_type(const std::string& name, const boot::type_info& info, std::shared_ptr<symbol_table> symbols)
+ static void declare_type(const std::string& name,
+ const boot::type_info& info, const std::shared_ptr<symbol_table>& symbols)
{
// The top level symbol table has basic (builtin) types in it which are not aliases.
if (auto alias_type = info.symbol.get<boot::alias_type>())
{
tree type_declaration = handle_symbol(name, alias_type, symbols);
- TREE_PUBLIC(type_declaration) = info.exported;
+ TREE_PUBLIC(type_declaration) = static_cast<unsigned>(info.exported);
}
}
- void rewrite_symbol_table(std::shared_ptr<boot::symbol_table> info_table, std::shared_ptr<symbol_table> symbols)
+ void rewrite_symbol_table(const std::shared_ptr<boot::symbol_table>& info_table,
+ const std::shared_ptr<symbol_table>& symbols)
{
for (auto& [symbol_name, symbol_info] : *info_table)
{
diff --git a/gcc/gcc/elna-diagnostic.cc b/gcc/gcc/elna-diagnostic.cc
index 630db0c..3dcdb98 100644
--- a/gcc/gcc/elna-diagnostic.cc
+++ b/gcc/gcc/elna-diagnostic.cc
@@ -26,7 +26,7 @@ namespace elna::gcc
linemap_add(line_table, LC_ENTER, 0, filename, 1);
}
- linemap_guard::linemap_guard(const std::filesystem::path filename)
+ linemap_guard::linemap_guard(const std::filesystem::path& filename)
{
const char *filename_pointer = ggc_strdup(filename.native().c_str());
@@ -35,7 +35,7 @@ namespace elna::gcc
linemap_guard::~linemap_guard()
{
- linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
+ linemap_add(line_table, LC_LEAVE, 0, nullptr, 0);
}
location_t get_location(const boot::source_position *position)
@@ -65,7 +65,7 @@ namespace elna::gcc
return make_location(caret, start, end);
}
- std::string print_aggregate_name(tree type, const std::string& kind_name)
+ static std::string print_aggregate_name(tree type, const std::string& kind_name)
{
if (TYPE_IDENTIFIER(type) == NULL_TREE)
{
diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc
index 43739fb..7491372 100644
--- a/gcc/gcc/elna-generic.cc
+++ b/gcc/gcc/elna-generic.cc
@@ -36,9 +36,9 @@ along with GCC; see the file COPYING3. If not see
namespace elna::gcc
{
- generic_visitor::generic_visitor(std::shared_ptr<symbol_table> symbol_table,
+ generic_visitor::generic_visitor(const std::shared_ptr<symbol_table>& symbol_table,
boot::symbol_bag bag, const boot::target_info& target)
- : bag(bag), symbols(symbol_table), target(target)
+ : bag(std::move(bag)), symbols(symbol_table), target(target)
, const_evaluator(std::make_unique<boot::evaluator>(this->bag, this->target,
this->evaluated_initializers))
{
@@ -58,7 +58,8 @@ namespace elna::gcc
argument_trees->quick_push(this->current_expression);
}
this->current_expression = fold_build_call_array_loc(call_location, TREE_TYPE(symbol_type),
- procedure_address, vec_safe_length(argument_trees), vec_safe_address(argument_trees));
+ procedure_address, static_cast<int>(vec_safe_length(argument_trees)),
+ vec_safe_address(argument_trees));
}
void generic_visitor::build_assert_builtin(location_t call_location,
@@ -343,6 +344,94 @@ namespace elna::gcc
finish_function(fndecl);
}
+ tree generic_visitor::build_equality(boot::binary_expression *expression, tree left, tree right)
+ {
+ tree_code equality_code;
+
+ if (expression->operation() == boot::binary_operator::equals)
+ {
+ equality_code = EQ_EXPR;
+ }
+ else if (expression->operation() == boot::binary_operator::not_equals)
+ {
+ equality_code = NE_EXPR;
+ }
+ else
+ {
+ gcc_unreachable();
+ }
+ return build_equality_comparison(get_location(&expression->position()), left, right,
+ expression->lhs().type_decoration, equality_code);
+ }
+
+ tree generic_visitor::build_equality_comparison(location_t loc, tree left, tree right,
+ const boot::type& left_type, tree_code equality_code)
+ {
+ tree_code combination_code = equality_code == EQ_EXPR
+ ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
+
+ if (left_type.get<boot::slice_type>() != nullptr)
+ {
+ tree lhs_ptr_field = TYPE_FIELDS(TREE_TYPE(left));
+ tree lhs_length_field = TREE_CHAIN(lhs_ptr_field);
+
+ tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field),
+ left, lhs_length_field, NULL_TREE);
+ tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field),
+ left, lhs_ptr_field, NULL_TREE);
+
+ tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field),
+ right, lhs_length_field, NULL_TREE);
+ tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field),
+ right, lhs_ptr_field, NULL_TREE);
+
+ tree element_size = fold_convert(elna_word_type_node,
+ size_in_bytes(TREE_TYPE(TREE_TYPE(lhs_ptr_field))));
+ tree byte_length = build2(MULT_EXPR, elna_word_type_node, lhs_length, element_size);
+
+ tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length);
+ tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp", integer_type_node,
+ lhs_ptr, rhs_ptr, byte_length);
+ tree equals_zero = build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node);
+
+ return build2(combination_code, elna_bool_type_node, length_equality, equals_zero);
+ }
+ else if (left_type.get<boot::record_type>() != nullptr
+ || left_type.get<boot::array_type>() != nullptr)
+ {
+ tree size = fold_convert(elna_word_type_node,
+ size_in_bytes(TREE_TYPE(left)));
+ tree lhs_addr = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(left)), left);
+ tree rhs_addr = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(right)), right);
+ tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp",
+ integer_type_node, lhs_addr, rhs_addr, size);
+ return build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node);
+ }
+ else
+ {
+ return build2_loc(loc, equality_code, elna_bool_type_node, left, right);
+ }
+ }
+
+ std::pair<tree, tree> generic_visitor::build_loop_head(tree control_variable_declaration,
+ tree limit, tree_code comparison, location_t check_location)
+ {
+ // Put a label in front of the loop condition.
+ tree check_label = create_artificial_label(check_location);
+ tree check_statement = build1_loc(check_location, LABEL_EXPR, void_type_node, check_label);
+ append_statement(check_statement);
+
+ // Build the condition and jump if the condition isn't met.
+ tree condition = fold_build2(comparison, elna_bool_type_node, control_variable_declaration, limit);
+ tree end_label = create_artificial_label(UNKNOWN_LOCATION);
+ tree goto_end = build1(GOTO_EXPR, void_type_node, end_label);
+ tree condition_statement = build3_loc(check_location, COND_EXPR, void_type_node,
+ condition, NULL_TREE, goto_end);
+ append_statement(condition_statement);
+
+ return { check_label, end_label };
+ }
+
void generic_visitor::enter_scope()
{
this->symbols = std::make_shared<symbol_table>(this->symbols);
@@ -396,7 +485,7 @@ namespace elna::gcc
cgraph_node::finalize_function(fndecl, true);
}
- static tree constant_to_tree(const boot::constant_value& constant_value)
+ static tree constant_to_tree(const boot::constant_value& constant_value, tree type = NULL_TREE)
{
if (std::holds_alternative<std::int32_t>(constant_value))
{
@@ -411,10 +500,12 @@ namespace elna::gcc
{
auto real_value = std::get<double>(constant_value);
REAL_VALUE_TYPE real;
- HOST_WIDE_INT target_bits[(sizeof(double) + sizeof(HOST_WIDE_INT) - 1)
- / sizeof(HOST_WIDE_INT)];
- std::memcpy(target_bits, &real_value, sizeof(real_value));
- real_from_target(&real, target_bits, REAL_MODE_FORMAT(TYPE_MODE(elna_float_type_node)));
+ constexpr std::size_t bits_size = (sizeof(double) + sizeof(HOST_WIDE_INT) - 1) / sizeof(HOST_WIDE_INT);
+ std::array<HOST_WIDE_INT, bits_size> target_bits;
+
+ std::memcpy(target_bits.data(), &real_value, sizeof(real_value));
+ real_from_target(&real, target_bits.data(), REAL_MODE_FORMAT(TYPE_MODE(elna_float_type_node)));
+
return build_real(elna_float_type_node, real);
}
else if (std::holds_alternative<bool>(constant_value))
@@ -431,11 +522,55 @@ namespace elna::gcc
}
else if (std::holds_alternative<boot::constant_aggregate<boot::ordered_map>>(constant_value))
{
- return NULL_TREE; // Compound constants are not lowered to trees yet.
+ // NOLINTNEXTLINE(readability-simplify-boolean-expr)
+ if (type == NULL_TREE || !RECORD_OR_UNION_TYPE_P(type))
+ {
+ return NULL_TREE;
+ }
+ const auto& aggregate = std::get<boot::constant_aggregate<boot::ordered_map>>(constant_value);
+ const auto& fields = *aggregate;
+ vec<constructor_elt, va_gc> *tree_arguments = nullptr;
+
+ 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 value_tree = constant_to_tree(field_value, TREE_TYPE(field_decl));
+ if (value_tree == NULL_TREE)
+ {
+ return NULL_TREE;
+ }
+ CONSTRUCTOR_APPEND_ELT(tree_arguments, field_decl, value_tree);
+ }
+ return build_constructor(type, tree_arguments);
}
else if (std::holds_alternative<boot::constant_aggregate<std::vector>>(constant_value))
{
- return NULL_TREE; // Compound constants are not lowered to trees yet.
+ if (type == NULL_TREE || TREE_CODE(type) != ARRAY_TYPE)
+ {
+ return NULL_TREE;
+ }
+ const auto& aggregate = std::get<boot::constant_aggregate<std::vector>>(constant_value);
+ const auto& elements = *aggregate;
+ tree domain = TYPE_DOMAIN(type);
+ tree index = TYPE_MIN_VALUE(domain);
+ tree element_type = TREE_TYPE(type);
+ vec<constructor_elt, va_gc> *tree_arguments = nullptr;
+
+ for (const auto& element : elements)
+ {
+ tree element_tree = constant_to_tree(element, element_type);
+ if (element_tree == NULL_TREE)
+ {
+ return NULL_TREE;
+ }
+ CONSTRUCTOR_APPEND_ELT(tree_arguments, index, element_tree);
+ index = int_const_binop(PLUS_EXPR, index, elna_word_one_node);
+ }
+ return build_constructor(type, tree_arguments);
}
return NULL_TREE;
}
@@ -506,75 +641,6 @@ namespace elna::gcc
this->current_expression = build_constructor(slice_type, elms);
}
- tree generic_visitor::build_equality(boot::binary_expression *expression, tree left, tree right)
- {
- tree_code equality_code;
-
- if (expression->operation() == boot::binary_operator::equals)
- {
- equality_code = EQ_EXPR;
- }
- else if (expression->operation() == boot::binary_operator::not_equals)
- {
- equality_code = NE_EXPR;
- }
- else
- {
- gcc_unreachable();
- }
- return build_equality_comparison(get_location(&expression->position()), left, right,
- expression->lhs().type_decoration, equality_code);
- }
-
- tree generic_visitor::build_equality_comparison(location_t loc, tree left, tree right,
- const boot::type& left_type, tree_code equality_code)
- {
- tree_code combination_code = equality_code == EQ_EXPR
- ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR;
-
- if (left_type.get<boot::slice_type>() != nullptr)
- {
- tree lhs_ptr_field = TYPE_FIELDS(TREE_TYPE(left));
- tree lhs_length_field = TREE_CHAIN(lhs_ptr_field);
-
- tree lhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field),
- left, lhs_length_field, NULL_TREE);
- tree lhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field),
- left, lhs_ptr_field, NULL_TREE);
-
- tree rhs_length = build3(COMPONENT_REF, TREE_TYPE(lhs_length_field),
- right, lhs_length_field, NULL_TREE);
- tree rhs_ptr = build3(COMPONENT_REF, TREE_TYPE(lhs_ptr_field),
- right, lhs_ptr_field, NULL_TREE);
-
- tree element_size = fold_convert(elna_word_type_node,
- size_in_bytes(TREE_TYPE(TREE_TYPE(lhs_ptr_field))));
- tree byte_length = build2(MULT_EXPR, elna_word_type_node, lhs_length, element_size);
-
- tree length_equality = build2(equality_code, elna_bool_type_node, lhs_length, rhs_length);
- tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp", integer_type_node,
- lhs_ptr, rhs_ptr, byte_length);
- tree equals_zero = build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node);
-
- return build2(combination_code, elna_bool_type_node, length_equality, equals_zero);
- }
- else if (left_type.get<boot::record_type>() != nullptr
- || left_type.get<boot::array_type>() != nullptr)
- {
- tree size = fold_convert(elna_word_type_node,
- size_in_bytes(TREE_TYPE(left)));
- tree lhs_addr = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(left)), left);
- tree rhs_addr = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(right)), right);
- tree memcmp_call = call_built_in(UNKNOWN_LOCATION, "__builtin_memcmp",
- integer_type_node, lhs_addr, rhs_addr, size);
- return build2(equality_code, elna_bool_type_node, memcmp_call, integer_zero_node);
- }
- else
- {
- return build2_loc(loc, equality_code, elna_bool_type_node, left, right);
- }
- }
-
void generic_visitor::visit(boot::binary_expression *expression)
{
expression->lhs().accept(this);
@@ -746,7 +812,7 @@ namespace elna::gcc
boot::evaluator constant_evaluator(this->bag, this->target, evaluated_initializers);
if (auto constant_value = constant_evaluator.evaluate(*declaration->initializer))
{
- tree folded = constant_to_tree(constant_value.value());
+ tree folded = constant_to_tree(constant_value.value(), TREE_TYPE(declaration_tree));
if (folded != NULL_TREE)
{
initializer_tree = folded;
@@ -779,7 +845,8 @@ namespace elna::gcc
if (lang_hooks.decls.global_bindings_p())
{
- TREE_STATIC(declaration_tree) = !variable_identifier.exported() && !declaration->is_extern;
+ TREE_STATIC(declaration_tree) =
+ static_cast<unsigned>(!variable_identifier.exported() && !declaration->is_extern);
varpool_node::get_create(declaration_tree);
varpool_node::finalize_decl(declaration_tree);
}
@@ -788,7 +855,7 @@ namespace elna::gcc
DECL_CONTEXT(declaration_tree) = current_function_decl;
f_binding_level->names = chainon(f_binding_level->names, declaration_tree);
- auto *declaration_statement = build1_loc(declaration_location, DECL_EXPR,
+ tree declaration_statement = build1_loc(declaration_location, DECL_EXPR,
void_type_node, declaration_tree);
append_statement(declaration_statement);
}
@@ -797,7 +864,7 @@ namespace elna::gcc
void generic_visitor::visit(boot::named_expression *expression)
{
- auto symbol = this->symbols->lookup(expression->name);
+ tree symbol = this->symbols->lookup(expression->name);
if (symbol == NULL_TREE)
{
@@ -851,66 +918,27 @@ namespace elna::gcc
}
}
- bool generic_visitor::expect_trait_type_only(boot::traits_expression *trait)
- {
- if (trait->arguments.size() != 1)
- {
- error_at(get_location(&trait->position()), "Trait '%s' expects 1 argument, got %lu",
- trait->name.name().c_str(), trait->arguments.size());
- this->current_expression = error_mark_node;
- return false;
- }
- this->current_expression = get_inner_alias(trait->types.front(), this->symbols);
-
- return this->current_expression != error_mark_node;
- }
-
void generic_visitor::visit(boot::traits_expression *trait)
{
location_t trait_location = get_location(&trait->position());
- if (trait->name == "size")
+ if (trait->name == "size" || trait->name == "alignment"
+ || trait->name == "min" || trait->name == "max")
{
- if (expect_trait_type_only(trait))
+ if (trait->arguments.size() != 1)
{
- if (auto value = this->const_evaluator->evaluate_traits(*trait))
- {
- this->current_expression = constant_to_tree(*value);
- }
- else
- {
- this->current_expression = fold_convert_loc(trait_location,
- elna_word_type_node, size_in_bytes(this->current_expression));
- }
+ error_at(trait_location, "Trait '%s' expects 1 argument, got %lu",
+ trait->name.name().c_str(), trait->arguments.size());
+ this->current_expression = error_mark_node;
+ return;
}
- }
- else if (trait->name == "alignment")
- {
- if (expect_trait_type_only(trait))
+ if (auto value = this->const_evaluator->evaluate_traits(*trait))
{
- if (auto value = this->const_evaluator->evaluate_traits(*trait))
- {
- this->current_expression = constant_to_tree(*value);
- }
- else
- {
- this->current_expression = build_int_cstu(elna_word_type_node,
- TYPE_ALIGN_UNIT(this->current_expression));
- }
+ this->current_expression = constant_to_tree(*value);
}
- }
- else if (trait->name == "min" || trait->name == "max")
- {
- if (expect_trait_type_only(trait))
+ else
{
- if (auto value = this->const_evaluator->evaluate_traits(*trait))
- {
- this->current_expression = constant_to_tree(*value);
- }
- else
- {
- this->current_expression = error_mark_node;
- }
+ this->current_expression = error_mark_node;
}
}
else if (trait->name == "offset")
@@ -922,7 +950,6 @@ namespace elna::gcc
this->current_expression = error_mark_node;
return;
}
- this->current_expression = get_inner_alias(trait->types.front(), this->symbols);
auto *field_type = trait->arguments.at(1)->is_named();
if (field_type == nullptr)
@@ -933,12 +960,9 @@ namespace elna::gcc
this->current_expression = error_mark_node;
return;
}
- tree field_declaration = find_field_by_name(trait_location, this->current_expression, field_type->name);
-
- if (field_declaration != error_mark_node)
+ if (auto value = this->const_evaluator->evaluate_traits(*trait))
{
- this->current_expression = fold_convert_loc(trait_location, elna_word_type_node,
- byte_position(field_declaration));
+ this->current_expression = constant_to_tree(*value);
}
else
{
@@ -1099,25 +1123,6 @@ namespace elna::gcc
return decl;
}
- std::pair<tree, tree> generic_visitor::build_loop_head(tree control_variable_declaration, tree limit,
- tree_code comparison, location_t check_location)
- {
- // Put a label in front of the loop condition.
- tree check_label = create_artificial_label(check_location);
- tree check_statement = build1_loc(check_location, LABEL_EXPR, void_type_node, check_label);
- append_statement(check_statement);
-
- // Build the condition and jump if the condition isn't met.
- tree condition = fold_build2(comparison, elna_bool_type_node, control_variable_declaration, limit);
- tree end_label = create_artificial_label(UNKNOWN_LOCATION);
- tree goto_end = build1(GOTO_EXPR, void_type_node, end_label);
- tree condition_statement = build3_loc(check_location, COND_EXPR, void_type_node,
- condition, NULL_TREE, goto_end);
- append_statement(condition_statement);
-
- return { check_label, end_label };
- }
-
void generic_visitor::visit(boot::repeat_statement *statement)
{
enter_scope();
diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc
index c47bb94..e8a7daa 100644
--- a/gcc/gcc/elna-tree.cc
+++ b/gcc/gcc/elna-tree.cc
@@ -25,6 +25,29 @@ along with GCC; see the file COPYING3. If not see
namespace elna::gcc
{
+ const elna::boot::target_info& get_host_target()
+ {
+ static const elna::boot::target_info info = []{
+ elna::boot::target_info target_info;
+
+ target_info.int_properties.size = TYPE_PRECISION(elna_int_type_node) / BITS_PER_UNIT;
+ target_info.int_properties.alignment = TYPE_ALIGN_UNIT(elna_int_type_node);
+ target_info.word_properties.size = TYPE_PRECISION(elna_word_type_node) / BITS_PER_UNIT;
+ target_info.word_properties.alignment = TYPE_ALIGN_UNIT(elna_word_type_node);
+ target_info.pointer_properties.size = TYPE_PRECISION(ptr_type_node) / BITS_PER_UNIT;
+ target_info.pointer_properties.alignment = TYPE_ALIGN_UNIT(ptr_type_node);
+ target_info.char_properties.size = TYPE_PRECISION(elna_char_type_node) / BITS_PER_UNIT;
+ target_info.char_properties.alignment = TYPE_ALIGN_UNIT(elna_char_type_node);
+ target_info.float_properties.size = TYPE_PRECISION(elna_float_type_node) / BITS_PER_UNIT;
+ target_info.float_properties.alignment = TYPE_ALIGN_UNIT(elna_float_type_node);
+ target_info.bool_properties.size = (TYPE_PRECISION(elna_bool_type_node) + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
+ target_info.bool_properties.alignment = TYPE_ALIGN_UNIT(elna_bool_type_node);
+
+ return target_info;
+ }();
+ return info;
+ }
+
bool is_integral_type(tree type)
{
gcc_assert(TYPE_P(type));
@@ -74,7 +97,7 @@ namespace elna::gcc
void defer(tree statement_tree)
{
- defer_scope new_defer{ statement_tree, alloc_stmt_list() };
+ defer_scope new_defer{ .defer_block = statement_tree, .try_statements = alloc_stmt_list() };
vec_safe_insert(f_binding_level->defers, 0, new_defer);
}
@@ -87,9 +110,9 @@ namespace elna::gcc
defer_scope *defer_iterator = f_binding_level->defers->begin();
tree defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
defer_iterator->try_statements, defer_iterator->defer_block);
- int i;
+ int index;
- FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, i, defer_iterator, 1)
+ FOR_EACH_VEC_ELT_FROM(*f_binding_level->defers, index, defer_iterator, 1)
{
append_to_statement_list(defer_tree, &defer_iterator->try_statements);
defer_tree = build2(TRY_FINALLY_EXPR, void_type_node,
@@ -98,7 +121,7 @@ namespace elna::gcc
return build2(COMPOUND_EXPR, TREE_TYPE(defer_tree), f_binding_level->statement_list, defer_tree);
}
- tree build_field(location_t location, tree record_type, const std::string name, tree type)
+ tree build_field(location_t location, tree record_type, const std::string& name, tree type)
{
tree field_declaration = build_decl(location,
FIELD_DECL, get_identifier(name.c_str()), type);
@@ -174,7 +197,7 @@ namespace elna::gcc
return type;
}
tree field_declaration = TYPE_FIELDS(type);
-
+ // NOLINTNEXTLINE(readability-simplify-boolean-expr)
if (!RECORD_OR_UNION_TYPE_P(type))
{
error_at(expression_location, "Type '%s' does not have a field named '%s'",
@@ -211,12 +234,12 @@ namespace elna::gcc
tree build_enumeration_type(const std::vector<std::string>& members)
{
tree composite_type_node = make_node(ENUMERAL_TYPE);
- const tree base_type = integer_type_node;
+ tree base_type = integer_type_node;
TREE_TYPE(composite_type_node) = base_type;
ENUM_IS_SCOPED(composite_type_node) = 1;
- tree *pp = &TYPE_VALUES(composite_type_node);
+ tree *members_pointer = &TYPE_VALUES(composite_type_node);
std::size_t order{ 1 };
for (const std::string& member : members)
@@ -231,8 +254,8 @@ namespace elna::gcc
TYPE_MAX_VALUE(composite_type_node) = DECL_INITIAL(member_declaration);
- *pp = build_tree_list(member_name, member_declaration);
- pp = &TREE_CHAIN(*pp);
+ *members_pointer = build_tree_list(member_name, member_declaration);
+ members_pointer = &TREE_CHAIN(*members_pointer);
}
TYPE_MIN_VALUE(composite_type_node) = DECL_INITIAL(TREE_VALUE(TYPE_VALUES(composite_type_node)));
TYPE_UNSIGNED(composite_type_node) = TYPE_UNSIGNED(base_type);
diff --git a/gcc/gcc/elna1.cc b/gcc/gcc/elna1.cc
index fde2adc..8eb103b 100644
--- a/gcc/gcc/elna1.cc
+++ b/gcc/gcc/elna1.cc
@@ -52,29 +52,6 @@ union GTY ((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
/* Language hooks. */
-static const elna::boot::target_info& get_host_target()
-{
- static const elna::boot::target_info info = []{
- elna::boot::target_info target_info;
-
- target_info.int_size = TYPE_PRECISION(elna_int_type_node) / BITS_PER_UNIT;
- target_info.int_alignment = TYPE_ALIGN_UNIT(elna_int_type_node);
- target_info.word_size = TYPE_PRECISION(elna_word_type_node) / BITS_PER_UNIT;
- target_info.word_alignment = TYPE_ALIGN_UNIT(elna_word_type_node);
- target_info.pointer_size = TYPE_PRECISION(ptr_type_node) / BITS_PER_UNIT;
- target_info.pointer_alignment = TYPE_ALIGN_UNIT(ptr_type_node);
- target_info.char_size = TYPE_PRECISION(elna_char_type_node) / BITS_PER_UNIT;
- target_info.char_alignment = TYPE_ALIGN_UNIT(elna_char_type_node);
- target_info.float_size = TYPE_PRECISION(elna_float_type_node) / BITS_PER_UNIT;
- target_info.float_alignment = TYPE_ALIGN_UNIT(elna_float_type_node);
- target_info.bool_size = TYPE_PRECISION(elna_bool_type_node) / BITS_PER_UNIT;
- target_info.bool_alignment = TYPE_ALIGN_UNIT(elna_bool_type_node);
-
- return target_info;
- }();
- return info;
-}
-
static bool elna_langhook_init(void)
{
build_common_tree_nodes(false);
@@ -148,7 +125,7 @@ static elna::boot::dependency elna_parse_file(dependency_state& state, const cha
outcome_bag.add_import(cached_import->second);
}
}
- outcome.errors() = analyze_semantics(outcome.tree, outcome_bag, get_host_target());
+ outcome.errors() = analyze_semantics(outcome.tree, outcome_bag, elna::gcc::get_host_target());
}
if (outcome.has_errors())
{
@@ -172,7 +149,7 @@ static void elna_langhook_parse_file(void)
{
linemap_add(line_table, LC_ENTER, 0, in_fnames[i], 1);
elna::gcc::generic_visitor generic_visitor{ state.custom,
- state.find(in_fnames[i])->second, get_host_target() };
+ state.find(in_fnames[i])->second, elna::gcc::get_host_target() };
outcome.tree->accept(&generic_visitor);
linemap_add(line_table, LC_LEAVE, 0, NULL, 0);
}