diff options
Diffstat (limited to 'gcc')
| -rw-r--r-- | gcc/Make-lang.in | 1 | ||||
| -rw-r--r-- | gcc/gcc/elna-builtins.cc | 2 | ||||
| -rw-r--r-- | gcc/gcc/elna-generic.cc | 140 | ||||
| -rw-r--r-- | gcc/gcc/elna-tree.cc | 103 |
4 files changed, 137 insertions, 109 deletions
diff --git a/gcc/Make-lang.in b/gcc/Make-lang.in index 5b8b6a8..690d047 100644 --- a/gcc/Make-lang.in +++ b/gcc/Make-lang.in @@ -57,6 +57,7 @@ elna_OBJS = \ elna/type_check.o \ elna/symbol.o \ elna/result.o \ + elna/validation.o \ $(END) elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS) diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index 226de4a..7e47c30 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -19,6 +19,8 @@ along with GCC; see the file COPYING3. If not see #include "elna/gcc/elna1.h" #include "stor-layout.h" #include "stringpool.h" + +#include "elna/boot/evaluator.h" #include "elna/gcc/elna-tree.h" namespace elna::gcc diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 00581df..559d09c 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -16,10 +16,8 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ #include <array> -#include <cstring> #include <ranges> -#include "elna/boot/evaluator.h" #include "elna/gcc/elna-diagnostic.h" #include "elna/gcc/elna-generic.h" #include "elna/gcc/elna1.h" @@ -38,7 +36,8 @@ namespace elna::gcc { generic_visitor::generic_visitor(const std::shared_ptr<symbol_table>& symbol_table, boot::symbol_bag bag, const boot::target_info& target) - : bag(std::move(bag)), symbols(symbol_table), target(target) + : bag(std::move(bag)), symbols(symbol_table), target(target), + constant_evaluator(this->bag, this->target) { } @@ -483,104 +482,14 @@ namespace elna::gcc cgraph_node::finalize_function(fndecl, true); } - static tree constant_to_tree(const boot::constant_value& constant_value, tree type = NULL_TREE) - { - if (std::holds_alternative<std::int32_t>(constant_value)) - { - return build_int_cst(elna_int_type_node, std::get<std::int32_t>(constant_value)); - } - else if (std::holds_alternative<std::uint32_t>(constant_value)) - { - return build_int_cstu(elna_word_type_node, std::get<std::uint32_t>(constant_value)); - } - - else if (std::holds_alternative<double>(constant_value)) - { - auto real_value = std::get<double>(constant_value); - REAL_VALUE_TYPE real; - 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)) - { - return std::get<bool>(constant_value) ? boolean_true_node : boolean_false_node; - } - else if (std::holds_alternative<unsigned char>(constant_value)) - { - return build_int_cstu(elna_char_type_node, std::get<unsigned char>(constant_value)); - } - else if (std::holds_alternative<std::nullptr_t>(constant_value)) - { - return null_pointer_node; - } - else if (std::holds_alternative<boot::constant_aggregate<boot::ordered_map>>(constant_value)) - { - // 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)) - { - 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; - } - void generic_visitor::visit(boot::literal<std::int32_t> *literal) { - this->current_expression = constant_to_tree(boot::constant_value{ literal->value }); + this->current_expression = constant_to_tree(boot::constant_value{ literal->value }, this->symbols); } void generic_visitor::visit(boot::literal<std::uint32_t> *literal) { - this->current_expression = constant_to_tree(boot::constant_value{ literal->value }); + this->current_expression = constant_to_tree(boot::constant_value{ literal->value }, this->symbols); } void generic_visitor::visit(boot::literal<double> *literal) @@ -600,17 +509,17 @@ namespace elna::gcc void generic_visitor::visit(boot::literal<bool> *boolean) { - this->current_expression = constant_to_tree(boot::constant_value{ boolean->value }); + this->current_expression = constant_to_tree(boot::constant_value{ boolean->value }, this->symbols); } void generic_visitor::visit(boot::literal<unsigned char> *character) { - this->current_expression = constant_to_tree(boot::constant_value{ character->value }); + this->current_expression = constant_to_tree(boot::constant_value{ character->value }, this->symbols); } void generic_visitor::visit(boot::literal<std::nullptr_t> *) { - this->current_expression = constant_to_tree(boot::constant_value{ std::nullptr_t{} }); + this->current_expression = constant_to_tree(boot::constant_value{ std::nullptr_t{} }, this->symbols); } void generic_visitor::visit(boot::literal<std::string> *string) @@ -639,6 +548,19 @@ namespace elna::gcc this->current_expression = build_constructor(slice_type, elms); } + void generic_visitor::visit(boot::traits_expression *trait) + { + auto value = this->constant_evaluator.evaluate_traits(*trait); + + if (!value.has_value()) + { + this->current_expression = error_mark_node; + return; + } + tree type = get_inner_alias(trait->type_decoration, this->symbols); + this->current_expression = constant_to_tree(value.value(), this->symbols, type); + } + void generic_visitor::visit(boot::binary_expression *expression) { expression->lhs().accept(this); @@ -794,15 +716,19 @@ namespace elna::gcc location_t declaration_location = get_location(&declaration->position()); tree declaration_tree = this->symbols->lookup(variable_identifier.name()); + auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable(); + if (declaration_tree == NULL_TREE) { - auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable(); - declaration_tree = declare_variable(variable_identifier.name(), *variable_symbol, this->symbols); } - // Set initializer if given. The constant_folder pass has - // already folded the initializer into literals at this point. - if (declaration->initializer != nullptr) + if (variable_symbol->value.has_value()) + { + tree type = get_inner_alias(variable_symbol->symbol, this->symbols); + DECL_INITIAL(declaration_tree) = constant_to_tree( + variable_symbol->value.value(), this->symbols, type); + } + else if (declaration->initializer != nullptr) { declaration->initializer->accept(this); DECL_INITIAL(declaration_tree) = this->current_expression; @@ -811,13 +737,9 @@ namespace elna::gcc { DECL_INITIAL(declaration_tree) = null_pointer_node; } + if (variable_symbol->symbol.get<boot::constant_type>() != nullptr) { - auto variable_symbol = this->bag.lookup(variable_identifier.name())->is_variable(); - - if (variable_symbol != nullptr && variable_symbol->symbol.get<boot::constant_type>() != nullptr) - { - TREE_READONLY(declaration_tree) = 1; - } + TREE_READONLY(declaration_tree) = 1; } this->current_expression = NULL_TREE; diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc index e8a7daa..352d413 100644 --- a/gcc/gcc/elna-tree.cc +++ b/gcc/gcc/elna-tree.cc @@ -15,6 +15,9 @@ 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 <array> +#include <cstring> + #include "elna/gcc/elna-diagnostic.h" #include "elna/gcc/elna-tree.h" #include "elna/gcc/elna1.h" @@ -281,4 +284,104 @@ namespace elna::gcc } return NULL_TREE; } + + tree constant_to_tree(const boot::constant_value& constant_value, + const std::shared_ptr<symbol_table>& symbols, tree type) + { + if (std::holds_alternative<std::int32_t>(constant_value)) + { + return build_int_cst(elna_int_type_node, std::get<std::int32_t>(constant_value)); + } + else if (std::holds_alternative<std::uint32_t>(constant_value)) + { + return build_int_cstu(elna_word_type_node, std::get<std::uint32_t>(constant_value)); + } + else if (std::holds_alternative<double>(constant_value)) + { + auto real_value = std::get<double>(constant_value); + REAL_VALUE_TYPE real; + 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)) + { + return std::get<bool>(constant_value) ? boolean_true_node : boolean_false_node; + } + else if (std::holds_alternative<unsigned char>(constant_value)) + { + return build_int_cstu(elna_char_type_node, std::get<unsigned char>(constant_value)); + } + else if (std::holds_alternative<std::nullptr_t>(constant_value)) + { + return null_pointer_node; + } + else if (std::holds_alternative<boot::global_address>(constant_value)) + { + const auto& address = std::get<boot::global_address>(constant_value); + tree decl = symbols->lookup(address.name); + if (decl == NULL_TREE) + { + return NULL_TREE; + } + return build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(decl)), decl); + } + else if (std::holds_alternative<boot::constant_aggregate<boot::ordered_map>>(constant_value)) + { + // 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, symbols, 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)) + { + 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, symbols, 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; + } } |
