From 39269cc68a32f6e1a7524b00da36a1fe4cc7fb8b Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 21 Aug 2026 00:05:03 +0200 Subject: Implement Single and Double floats --- gcc/dg.exp | 10 +- gcc/gcc/elna-builtins.cc | 7 +- gcc/gcc/elna-generic.cc | 29 +++--- gcc/gcc/elna-tree.cc | 23 +++-- gcc/testlib/elna-dg.exp | 235 +---------------------------------------------- 5 files changed, 36 insertions(+), 268 deletions(-) (limited to 'gcc') diff --git a/gcc/dg.exp b/gcc/dg.exp index 71e7105..edbb371 100644 --- a/gcc/dg.exp +++ b/gcc/dg.exp @@ -22,11 +22,11 @@ load_lib elna-dg.exp # Initialize dg. dg-init -# Main loop. -# Single-module .elna files and multi-module directories, -# both exactly one level below the category directories. -elna-dg-runtest-single [lsort [glob -nocomplain $srcdir/$subdir/*/*.elna]] -elna-dg-runtest-multi [lsort [glob -nocomplain -type d $srcdir/$subdir/*/*]] +# Main loop. Single-module tests are files one level below the category +# directories, multi-module tests are directories one level below any +# category directory, with a sut.elna as the primary module. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*/*.elna]] "" "" +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*/*/sut.elna]] "" "" # All done. dg-finish diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc index 95ffb2f..9552abb 100644 --- a/gcc/gcc/elna-builtins.cc +++ b/gcc/gcc/elna-builtins.cc @@ -52,7 +52,8 @@ namespace elna::gcc }, .pointer_properties = get_host_numeric_properties(ptr_type_node), .char_properties = get_host_numeric_properties(elna_char_type_node), - .float_properties = get_host_numeric_properties(elna_float_type_node), + .single_properties = get_host_numeric_properties(float_type_node), + .double_properties = get_host_numeric_properties(double_type_node), .bool_properties = { .size = static_cast( (TYPE_PRECISION(elna_bool_type_node) + BITS_PER_UNIT - 1) / BITS_PER_UNIT), @@ -72,7 +73,6 @@ namespace elna::gcc TYPE_STRING_FLAG(elna_char_type_node) = 1; elna_pointer_type_node = ptr_type_node; - elna_float_type_node = double_type_node; elna_bool_type_node = boolean_type_node; elna_bool_true_node = boolean_true_node; @@ -109,7 +109,8 @@ namespace elna::gcc declare_builtin_type(builtin_table, "Char", elna_char_type_node); declare_builtin_type(builtin_table, "Bool", elna_bool_type_node); declare_builtin_type(builtin_table, "Pointer", elna_pointer_type_node); - declare_builtin_type(builtin_table, "Float", elna_float_type_node); + declare_builtin_type(builtin_table, "Single", float_type_node); + declare_builtin_type(builtin_table, "Double", double_type_node); return builtin_table; } diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 323ec09..fb898d5 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -29,7 +29,6 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "dumpfile.h" #include "stringpool.h" -#include "realmpfr.h" #include "fold-const.h" #include "langhooks.h" @@ -490,34 +489,29 @@ namespace elna::gcc this->symbols, literal_type); } - void generic_visitor::visit(boot::literal *literal) + void generic_visitor::visit(boot::literal *literal) { - REAL_VALUE_TYPE real_value1; - - mpfr_t number; - mpfr_init2(number, SIGNIFICAND_BITS); - mpfr_set_d(number, literal->value, MPFR_RNDN); - - real_from_mpfr(&real_value1, number, double_type_node, MPFR_RNDN); - - this->current_expression = build_real(double_type_node, real_value1); - - mpfr_clear(number); + tree literal_type = get_inner_alias(literal->type_decoration, this->symbols); + this->current_expression = constant_to_tree(boot::constant_value{ literal->value }, + this->symbols, literal_type); } void generic_visitor::visit(boot::literal *boolean) { - this->current_expression = constant_to_tree(boot::constant_value{ boolean->value }, this->symbols); + this->current_expression = constant_to_tree(boot::constant_value{ boolean->value }, + this->symbols, elna_bool_type_node); } void generic_visitor::visit(boot::literal *character) { - this->current_expression = constant_to_tree(boot::constant_value{ character->value }, this->symbols); + this->current_expression = constant_to_tree(boot::constant_value{ character->value }, + this->symbols, elna_char_type_node); } void generic_visitor::visit(boot::literal *) { - this->current_expression = constant_to_tree(boot::constant_value{ std::nullptr_t{} }, this->symbols); + this->current_expression = constant_to_tree(boot::constant_value{ std::nullptr_t{} }, + this->symbols, elna_pointer_type_node); } void generic_visitor::visit(boot::literal *string) @@ -579,7 +573,8 @@ namespace elna::gcc break; case division: this->current_expression = fold_build2_loc(expression_location, - TRUNC_DIV_EXPR, left_type, left, right); + SCALAR_FLOAT_TYPE_P(left_type) ? RDIV_EXPR : TRUNC_DIV_EXPR, + left_type, left, right); break; case remainder: this->current_expression = fold_build2_loc(expression_location, diff --git a/gcc/gcc/elna-tree.cc b/gcc/gcc/elna-tree.cc index 5284e42..e4c8a20 100644 --- a/gcc/gcc/elna-tree.cc +++ b/gcc/gcc/elna-tree.cc @@ -15,9 +15,6 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ -#include -#include - #include "elna/gcc/elna-diagnostic.h" #include "elna/gcc/elna-tree.h" #include "elna/gcc/elna1.h" @@ -25,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "stor-layout.h" #include "diagnostic-core.h" +#include "realmpfr.h" namespace elna::gcc { @@ -251,6 +249,8 @@ namespace elna::gcc tree constant_to_tree(const boot::constant_value& constant_value, const std::shared_ptr& symbols, tree type) { + gcc_assert(type != NULL_TREE); + if (std::holds_alternative(constant_value)) { auto literal_value = std::get(constant_value); @@ -272,17 +272,20 @@ namespace elna::gcc return NULL_TREE; } } - else if (std::holds_alternative(constant_value)) + else if (std::holds_alternative(constant_value)) { - auto real_value = std::get(constant_value); + auto literal = std::get(constant_value); + + mpfr_t number; + mpfr_init2(number, SIGNIFICAND_BITS); + mpfr_set_d(number, literal.value(), MPFR_RNDN); + REAL_VALUE_TYPE real; - constexpr std::size_t bits_size = (sizeof(double) + sizeof(long) - 1) / sizeof(long); - std::array target_bits; + real_from_mpfr(&real, number, type, MPFR_RNDN); - 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))); + mpfr_clear(number); - return build_real(elna_float_type_node, real); + return build_real(type, real); } else if (std::holds_alternative(constant_value)) { diff --git a/gcc/testlib/elna-dg.exp b/gcc/testlib/elna-dg.exp index 03620e3..773dd54 100644 --- a/gcc/testlib/elna-dg.exp +++ b/gcc/testlib/elna-dg.exp @@ -16,7 +16,9 @@ load_lib gcc-dg.exp +# # Define elna callbacks for dg.exp. +# proc elna-dg-test { prog do_what extra_tool_flags } { set result \ @@ -31,236 +33,3 @@ proc elna-dg-test { prog do_what extra_tool_flags } { proc elna-dg-prune { system text } { return [gcc-dg-prune $system $text] } - -# Utility routines. - -# -# Escapes a directive argument so that it reaches dejagnu intact. -# -# dg.exp evaluates each extracted directive as a Tcl script -# ("catch $op"), which performs one round of backslash, command and -# variable substitution inside the double-quoted argument. Quoting the -# affected characters here means the argument dejagnu receives is -# exactly what the test author wrote, so @Error messages keep their -# regular expression semantics: "\[2\]" matches literal brackets and -# "[2]" stays a character class. -# -proc elna-escape-directive { text } { - return [string map [list \ - "\\" "\\\\" \ - "\[" "\\\[" \ - "\]" "\\\]" \ - "\$" "\\\$" \ - "\"" "\\\""] $text] -} - -# -# Replaces an elna-native directive in the line with its dg-* equivalent, -# escaping the directive argument for dejagnu's Tcl evaluation. -# -# line_var - name of the variable holding the line in the caller. -# directive - elna directive name, e.g. @Error. -# dg_name - dejagnu directive name, e.g. dg-error. -# -proc elna-convert-directive { line_var directive dg_name } { - upvar 1 $line_var line - - if { [regexp -indices "\\(\\*\\s*$directive\\s+(.*?)\\s*\\*\\)" $line whole argument] } { - set escaped [elna-escape-directive \ - [string range $line [lindex $argument 0] [lindex $argument 1]]] - set prefix [string range $line 0 [expr {[lindex $whole 0] - 1}]] - set suffix [string range $line [expr {[lindex $whole 1] + 1}] end] - - set line "${prefix}(* { $dg_name \"$escaped\" } *)$suffix" - } -} - -# -# This procedure copies a test file from the source tree to the -# build directory while rewriting elna-native directives to dejagnu -# dg-* equivalents. -# -# Directives (inside (* ... *) comments): -# -# (* @Error message *) Expected compiler error on this line. -# (* @Flags args *) Extra compiler flags. -# -# base - absolute path to the source directory, e.g. .../testsuite/elna.dg -# test - relative path from testsuite, e.g. fail_compilation/file_name.elna -# -# -# Creates a directory at $path, handling the case where a regular -# file already exists at that location (leftover from a prior -# interrupted run). -# -proc elna-ensure-dir { path } { - if { [file exists $path] && ![file isdirectory $path] } { - file delete $path - } - file mkdir $path -} - -proc elna-convert-test { base test { extra_lines "" } } { - set type [file dirname $test] - set target $test - - # Opens a file in the build directory for writing and the source - # file for reading. - elna-ensure-dir $type - set fin [open $base/$target r] - set fout [open $target w] - - # Reads the source test file line by line and replace directives with - # Elna equivalents using a regular expression. - while { [gets $fin line] >= 0 } { - elna-convert-directive line @Error dg-error - elna-convert-directive line @Flags dg-additional-options - puts $fout $line - } - - close $fin - - # Append caller-supplied extra directives (e.g. dg-additional-sources). - foreach line $extra_lines { - puts $fout $line - } - - # Suppress excess output so stray diagnostics do not fail the test. - puts $fout "(* { dg-prune-output .* } *)" - - # Emit category-specific expectation. - set category [lindex [file split $test] 0] - switch $category { - compilable { - # Assert that an output file was produced. - puts $fout "(* { dg-final { output-exists } } *)" - } - fail_compilation { - # Assert that no output file was produced. - puts $fout "(* { dg-final { output-exists-not } } *)" - } - # Other cases are handled automatically. - } - - close $fout - - # Reaches up one stack frame (into the runtest proc) and links the - # caller's cleanup_extra_files variable to the local name cleanups. - upvar 1 cleanup_extra_files cleanups - # This ensures the converted file gets deleted after the test runs. - lappend cleanups $target - - return $target -} - -# -# Handles a multi-module test directory. -# -# Requires sut.elna (system under test) as the primary module; -# all other .elna files are passed as dg-additional-sources. -# -# base - absolute path to the source directory. -# test - relative path from testsuite, e.g. group/test_name. -# -proc elna-handle-multimodule { base test } { - upvar 1 cleanup_extra_files cleanups - - set dir "$base/$test" - - # Find all .elna files recursively inside the test directory. - set modules [lsort [find $dir *.elna]] - if { [llength $modules] == 0 } { - return "" - } - - # Allocate sut.elna as the primary module, collect the rest. - set main_module "" - set extra_sources "" - foreach module $modules { - if { [file tail $module] == "sut.elna" } { - set main_module $module - } else { - lappend extra_sources $module - } - } - if { $main_module == "" } { - error "multi-module test directory \"$test\" must contain sut.elna" - } - - # Build extra directives: -I for imports and dg-additional-sources. - set extra_lines "" - lappend extra_lines "(* { dg-additional-options \"-I$dir\" } *)" - elna-ensure-dir $test - foreach src $extra_sources { - set src_rel [string range $src [expr {[string length $dir] + 1}] end] - file copy $src $test - lappend cleanups [file join $test $src_rel] - lappend extra_lines "(* { dg-additional-sources \"$src_rel\" } *)" - } - - # Convert the primary module, passing the extra directives. - set main_rel [file join $test [file tail $main_module]] - return [elna-convert-test $base $main_rel $extra_lines] -} - -# -# Runs a converted test file through dejagnu and cleans up afterwards. -# -proc elna-dg-run-one { target type cleanup_extra_files } { - global dg-do-what-default - - switch $type { - runnable { set dg-do-what-default "run" } - default { set dg-do-what-default "compile" } - } - - dg-test $target "" "" - file delete $target - foreach srcfile $cleanup_extra_files { - file delete $srcfile - } -} - -# -# Converts and runs single-module .elna test files. -# -proc elna-dg-runtest-single { testcases } { - global dg-do-what-default - set saved-dg-do-what-default ${dg-do-what-default} - - foreach test $testcases { - set type [file tail [file dirname $test]] - set name [file tail $test] - set base [file dirname [file dirname $test]] - set cleanup_extra_files "" - - set target [elna-convert-test $base $type/$name] - elna-dg-run-one $target $type $cleanup_extra_files - } - - set dg-do-what-default ${saved-dg-do-what-default} -} - -# -# Converts and runs multi-module test directories. -# -proc elna-dg-runtest-multi { testcases } { - global dg-do-what-default - set saved-dg-do-what-default ${dg-do-what-default} - - foreach test $testcases { - set type [file tail [file dirname $test]] - set name [file tail $test] - set base [file dirname [file dirname $test]] - set cleanup_extra_files "" - - set target [elna-handle-multimodule $base $type/$name] - if { $target == "" } { - continue - } - - elna-dg-run-one $target $type $cleanup_extra_files - } - - set dg-do-what-default ${saved-dg-do-what-default} -} -- cgit v1.2.3