aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2026-10-03 01:15:24 +0200
committerEugen Wissner <belka@caraus.de>2026-10-03 01:15:24 +0200
commit2ea84997ae37517729c3c8ed3af8a000bdc632df (patch)
tree97f93b33d1e71beb02e93e6edcd0ae5b05a13817
parent128a564be05afb1cb2ec76884a81c2bd536899fd (diff)
downloadelna-2ea84997ae37517729c3c8ed3af8a000bdc632df.tar.gz
Calculate #min and max based on target architecture
-rw-r--r--boot/evaluator.cc23
-rw-r--r--gcc/gcc/elna-builtins.cc33
-rw-r--r--include/elna/boot/result.h22
-rw-r--r--testsuite/runnable/min_max.elna12
4 files changed, 78 insertions, 12 deletions
diff --git a/boot/evaluator.cc b/boot/evaluator.cc
index 6cf287c..67fc42a 100644
--- a/boot/evaluator.cc
+++ b/boot/evaluator.cc
@@ -21,7 +21,6 @@ along with GCC; see the file COPYING3. If not see
#include <cmath>
#include <cstddef>
-#include <limits>
#include <ranges>
namespace elna::boot
@@ -1048,15 +1047,18 @@ namespace elna::boot
}
if (is_primitive_type(resolved, "Single"))
{
- return constant_value{ float_literal::from(std::numeric_limits<float>::min()) };
+ return constant_value{ float_literal::from(this->target.single_properties.min) };
}
if (is_primitive_type(resolved, "Double"))
{
- return constant_value{ float_literal::from(std::numeric_limits<double>::min()) };
+ return constant_value{ float_literal::from(this->target.double_properties.min) };
}
if (const auto enumeration = resolved.get<enumeration_type>())
{
- return constant_value{ integer_literal::from<std::size_t>(1) };
+ return constant_value{
+ integer_literal::from<std::size_t>(
+ this->target.word_properties.front().size, 1U).value()
+ };
}
}
else if (subject.name.name() == "max")
@@ -1085,7 +1087,8 @@ namespace elna::boot
}
if (is_primitive_type(resolved, "Char"))
{
- return constant_value{ std::numeric_limits<std::uint32_t>::max() };
+ constexpr std::uint32_t max_unicode_codepoint = 0x10FFFF;
+ return constant_value{ max_unicode_codepoint };
}
if (is_primitive_type(resolved, "Bool"))
{
@@ -1093,15 +1096,19 @@ namespace elna::boot
}
if (is_primitive_type(resolved, "Single"))
{
- return constant_value{ float_literal::from(std::numeric_limits<float>::max()) };
+ return constant_value{ float_literal::from(this->target.single_properties.max) };
}
if (is_primitive_type(resolved, "Double"))
{
- return constant_value{ float_literal::from(std::numeric_limits<double>::max()) };
+ return constant_value{ float_literal::from(this->target.double_properties.max) };
}
if (const auto enumeration = resolved.get<enumeration_type>())
{
- return constant_value{ integer_literal::from(enumeration->members.size()) };
+ return constant_value{
+ integer_literal::from<std::size_t>(
+ this->target.word_properties.front().size,
+ enumeration->members.size()).value()
+ };
}
}
else if (subject.name.name() == "offset")
diff --git a/gcc/gcc/elna-builtins.cc b/gcc/gcc/elna-builtins.cc
index 4a50967..fc43ebe 100644
--- a/gcc/gcc/elna-builtins.cc
+++ b/gcc/gcc/elna-builtins.cc
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#include "stor-layout.h"
#include "stringpool.h"
#include "varasm.h"
+#include "realmpfr.h"
#include "elna/boot/evaluator.h"
#include "elna/gcc/elna-tree.h"
@@ -36,6 +37,34 @@ namespace elna::gcc
};
}
+ static double real_to_double(const REAL_VALUE_TYPE& real)
+ {
+ mpfr_t number;
+ mpfr_init2(number, SIGNIFICAND_BITS);
+ mpfr_from_real(number, &real, MPFR_RNDN);
+ const double result = mpfr_get_d(number, MPFR_RNDN);
+ mpfr_clear(number);
+ return result;
+ }
+
+ template<typename T>
+ static boot::float_properties<T> get_host_float_properties(tree node)
+ {
+ REAL_VALUE_TYPE max_real;
+ real_maxval(&max_real, 0, TYPE_MODE(node));
+ const double max_val = real_to_double(max_real);
+
+ REAL_VALUE_TYPE min_real;
+ real_maxval(&min_real, 1, TYPE_MODE(node));
+ const double min_val = real_to_double(min_real);
+
+ return boot::float_properties<T>{
+ get_host_numeric_properties(node),
+ static_cast<T>(min_val),
+ static_cast<T>(max_val)
+ };
+ }
+
const boot::target_info& get_host_target()
{
static const boot::target_info info = boot::target_info{
@@ -55,8 +84,8 @@ namespace elna::gcc
},
.pointer_properties = get_host_numeric_properties(ptr_type_node),
.char_properties = get_host_numeric_properties(elna_char_type_node),
- .single_properties = get_host_numeric_properties(float_type_node),
- .double_properties = get_host_numeric_properties(double_type_node),
+ .single_properties = get_host_float_properties<float>(float_type_node),
+ .double_properties = get_host_float_properties<double>(double_type_node),
.bool_properties = {
.size = static_cast<std::size_t>(
(TYPE_PRECISION(elna_bool_type_node) + BITS_PER_UNIT - 1) / BITS_PER_UNIT),
diff --git a/include/elna/boot/result.h b/include/elna/boot/result.h
index c7b79d3..540307c 100644
--- a/include/elna/boot/result.h
+++ b/include/elna/boot/result.h
@@ -826,6 +826,24 @@ namespace elna::boot
std::size_t alignment;
};
+ /**
+ * Properties of a floating point type on the target machine, including
+ * its minimum and maximum finite values.
+ */
+ template<typename T>
+ requires is_floating_point_v<T>
+ struct float_properties : type_properties
+ {
+ T min{};
+ T max{};
+
+ constexpr float_properties() = default;
+ constexpr float_properties(const type_properties& base, T min, T max)
+ : type_properties(base), min(min), max(max)
+ {
+ }
+ };
+
constexpr std::size_t target_integer_count = 5;
/**
@@ -837,8 +855,8 @@ namespace elna::boot
std::array<type_properties, target_integer_count> word_properties;
type_properties pointer_properties;
type_properties char_properties;
- type_properties single_properties;
- type_properties double_properties;
+ float_properties<float> single_properties;
+ float_properties<double> double_properties;
type_properties bool_properties;
/// C's \c int, the type narrower variadic arguments are promoted to.
type_properties c_int_properties;
diff --git a/testsuite/runnable/min_max.elna b/testsuite/runnable/min_max.elna
new file mode 100644
index 0000000..90873c8
--- /dev/null
+++ b/testsuite/runnable/min_max.elna
@@ -0,0 +1,12 @@
+program()
+type
+ Color = (red, green, blue)
+
+begin
+ assert(#min(Single) = -#max(Single));
+ assert(#min(Double) = -#max(Double));
+ assert(#min(Char) = `\0`);
+ assert(#max(Char) = `\{U+10FFFF}`);
+ assert(#min(Color) = Color.red);
+ assert(#max(Color) = Color.blue)
+end.