diff --git a/bastl/include/cfloat b/bastl/include/cfloat new file mode 100644 index 0000000..5d396f8 --- /dev/null +++ b/bastl/include/cfloat @@ -0,0 +1,9 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_CFLOAT_INCLUDED) +#define BAD_APPLE_OS_CFLOAT_INCLUDED + +#include + +#endif // !defined(BAD_APPLE_OS_CFLOAT_INCLUDED) diff --git a/bastl/include/climits b/bastl/include/climits new file mode 100644 index 0000000..ac01f81 --- /dev/null +++ b/bastl/include/climits @@ -0,0 +1,21 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_CLIMITS_INCLUDED) +#define BAD_APPLE_OS_CLIMITS_INCLUDED + +#include + +#if !defined(LLONG_MIN) +#define LLONG_MIN (-LLONG_MAX - 1LL) +#endif + +#if !defined(LLONG_MAX) +#define LLONG_MAX __LONG_LONG_MAX__ +#endif + +#if !defined(ULLONG_MAX) +#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL) +#endif + +#endif // !defined(BAD_APPLE_OS_CLIMITS_INCLUDED) diff --git a/bastl/include/cmath b/bastl/include/cmath new file mode 100644 index 0000000..07c99ac --- /dev/null +++ b/bastl/include/cmath @@ -0,0 +1,9 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_CMATH_INCLUDED) +#define BAD_APPLE_OS_CMATH_INCLUDED + +#include + +#endif // !defined(BAD_APPLE_OS_CMATH_INCLUDED) diff --git a/bastl/include/limits b/bastl/include/limits new file mode 100644 index 0000000..d9c160f --- /dev/null +++ b/bastl/include/limits @@ -0,0 +1,477 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_LIMITS_INCLUDED) +#define BAD_APPLE_OS_LIMITS_INCLUDED + +#include +#include +#include +#include + +namespace std +{ +namespace detail +{ +inline constexpr double LOG10_2 = 0.3010299956639812; +} +enum float_round_style +{ + round_indeterminate = -1, + round_toward_zero = 0, + round_to_nearest = 1, + round_toward_infinity = 2, + round_toward_neg_infinity = 3 +}; + +template +class numeric_limits +{ +public: + static constexpr bool is_specialized = false; + static constexpr bool is_signed = false; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_round_style round_style = round_toward_zero; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = false; + static constexpr bool is_modulo = false; + static constexpr int digits = 0; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 0; + static constexpr int radix = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool traps = false; + static constexpr bool tinyness_before = false; + + static constexpr T min() noexcept { return T(); } + static constexpr T lowest() noexcept { return T(); } + static constexpr T max() noexcept { return T(); } + static constexpr T epsilon() noexcept { return T(); } + static constexpr T round_error() noexcept { return T(); } + static constexpr T infinity() noexcept { return T(); } + static constexpr T quiet_NaN() noexcept { return T(); } + static constexpr T signaling_NaN() noexcept { return T(); } + static constexpr T denorm_min() noexcept { return T(); } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr int digits = 1; + static constexpr int radix = 2; + + static constexpr bool min() noexcept { return false; } + static constexpr bool lowest() noexcept { return false; } + static constexpr bool max() noexcept { return true; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = (CHAR_MIN < 0); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = (CHAR_BIT - is_signed); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr char min() noexcept { return CHAR_MIN; } + static constexpr char lowest() noexcept { return CHAR_MIN; } + static constexpr char max() noexcept { return CHAR_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = (CHAR_BIT - 1); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr signed char min() noexcept { return SCHAR_MIN; } + static constexpr signed char lowest() noexcept { return SCHAR_MIN; } + static constexpr signed char max() noexcept { return SCHAR_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT; + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr unsigned char min() noexcept { return 0; } + static constexpr unsigned char lowest() noexcept { return 0; } + static constexpr unsigned char max() noexcept { return UCHAR_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = (WCHAR_MIN < 0); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(wchar_t) - is_signed; + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr wchar_t min() noexcept { return WCHAR_MIN; } + static constexpr wchar_t lowest() noexcept { return WCHAR_MIN; } + static constexpr wchar_t max() noexcept { return WCHAR_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT; + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr char8_t min() noexcept { return 0; } + static constexpr char8_t lowest() noexcept { return 0; } + static constexpr char8_t max() noexcept { return UCHAR_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(char16_t); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr char16_t min() noexcept { return 0; } + static constexpr char16_t lowest() noexcept { return 0; } + static constexpr char16_t max() noexcept { return UINT_LEAST16_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(char32_t); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr char32_t min() noexcept { return 0; } + static constexpr char32_t lowest() noexcept { return 0; } + static constexpr char32_t max() noexcept { return UINT_LEAST32_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(short) - 1; + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr short min() noexcept { return SHRT_MIN; } + static constexpr short lowest() noexcept { return SHRT_MIN; } + static constexpr short max() noexcept { return SHRT_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(short); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr unsigned short min() noexcept { return 0; } + static constexpr unsigned short lowest() noexcept { return 0; } + static constexpr unsigned short max() noexcept { return USHRT_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(int) - 1; + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr int min() noexcept { return INT_MIN; } + static constexpr int lowest() noexcept { return INT_MIN; } + static constexpr int max() noexcept { return INT_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(int); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr unsigned int min() noexcept { return 0; } + static constexpr unsigned int lowest() noexcept { return 0; } + static constexpr unsigned int max() noexcept { return UINT_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(long) - 1; + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr long min() noexcept { return LONG_MIN; } + static constexpr long lowest() noexcept { return LONG_MIN; } + static constexpr long max() noexcept { return LONG_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(long); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr unsigned long min() noexcept { return 0; } + static constexpr unsigned long lowest() noexcept { return 0; } + static constexpr unsigned long max() noexcept { return ULONG_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(long long) - 1; + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr long long min() noexcept { return LLONG_MIN; } + static constexpr long long lowest() noexcept { return LLONG_MIN; } + static constexpr long long max() noexcept { return LLONG_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr int digits = CHAR_BIT * sizeof(long long); + static constexpr int digits10 = static_cast(digits * detail::LOG10_2); + static constexpr int radix = 2; + static constexpr bool traps = true; + + static constexpr unsigned long long min() noexcept { return 0; } + static constexpr unsigned long long lowest() noexcept { return 0; } + static constexpr unsigned long long max() noexcept { return ULLONG_MAX; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; + static constexpr float_round_style round_style = round_to_nearest; + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr int digits = FLT_MANT_DIG; + static constexpr int digits10 = FLT_DIG; + static constexpr int max_digits10 = FLT_DECIMAL_DIG; + static constexpr int radix = FLT_RADIX; + static constexpr int min_exponent = FLT_MIN_EXP; + static constexpr int min_exponent10 = FLT_MIN_10_EXP; + static constexpr int max_exponent = FLT_MAX_EXP; + static constexpr int max_exponent10 = FLT_MAX_10_EXP; + + static constexpr float min() noexcept { return FLT_MIN; } + static constexpr float lowest() noexcept { return -FLT_MAX; } + static constexpr float max() noexcept { return FLT_MAX; } + static constexpr float epsilon() noexcept { return FLT_EPSILON; } + static constexpr float round_error() noexcept { return 0.5f; } + static constexpr float infinity() noexcept { return HUGE_VALF; } + static constexpr float quiet_NaN() noexcept { return FLT_QNAN; } + static constexpr float signaling_NaN() noexcept { return FLT_SNAN; } + static constexpr float denorm_min() noexcept { return FLT_TRUE_MIN; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; + static constexpr float_round_style round_style = round_to_nearest; + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr int digits = DBL_MANT_DIG; + static constexpr int digits10 = DBL_DIG; + static constexpr int max_digits10 = DBL_DECIMAL_DIG; + static constexpr int radix = FLT_RADIX; + static constexpr int min_exponent = DBL_MIN_EXP; + static constexpr int min_exponent10 = DBL_MIN_10_EXP; + static constexpr int max_exponent = DBL_MAX_EXP; + static constexpr int max_exponent10 = DBL_MAX_10_EXP; + + static constexpr double min() noexcept { return DBL_MIN; } + static constexpr double lowest() noexcept { return -DBL_MAX; } + static constexpr double max() noexcept { return DBL_MAX; } + static constexpr double epsilon() noexcept { return DBL_EPSILON; } + static constexpr double round_error() noexcept { return 0.5; } + static constexpr double infinity() noexcept { return HUGE_VAL; } + static constexpr double quiet_NaN() noexcept { return DBL_QNAN; } + static constexpr double signaling_NaN() noexcept { return DBL_SNAN; } + static constexpr double denorm_min() noexcept { return DBL_TRUE_MIN; } +}; + +template<> +class numeric_limits +{ +public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = true; + static constexpr float_round_style round_style = round_to_nearest; + static constexpr bool is_iec559 = true; + static constexpr bool is_bounded = true; + static constexpr int digits = LDBL_MANT_DIG; + static constexpr int digits10 = LDBL_DIG; + static constexpr int max_digits10 = LDBL_DECIMAL_DIG; + static constexpr int radix = FLT_RADIX; + static constexpr int min_exponent = LDBL_MIN_EXP; + static constexpr int min_exponent10 = LDBL_MIN_10_EXP; + static constexpr int max_exponent = LDBL_MAX_EXP; + static constexpr int max_exponent10 = LDBL_MAX_10_EXP; + + static constexpr long double min() noexcept { return LDBL_MIN; } + static constexpr long double lowest() noexcept { return -LDBL_MAX; } + static constexpr long double max() noexcept { return LDBL_MAX; } + static constexpr long double epsilon() noexcept { return LDBL_EPSILON; } + static constexpr long double round_error() noexcept { return 0.5l; } + static constexpr long double infinity() noexcept { return HUGE_VALL; } + static constexpr long double quiet_NaN() noexcept { return LDBL_QNAN; } + static constexpr long double signaling_NaN() noexcept { return LDBL_SNAN; } + static constexpr long double denorm_min() noexcept { return LDBL_TRUE_MIN; } +}; +} + +#endif // !defined(BAD_APPLE_OS_LIMITS_INCLUDED) diff --git a/bastl/include/memory b/bastl/include/memory index 6c9b923..95aa5db 100644 --- a/bastl/include/memory +++ b/bastl/include/memory @@ -5,9 +5,42 @@ #define BAD_APPLE_OS_MEMORY_HPP_INCLUDED #include +#include +#include +#include +#include namespace std { +template +struct allocator +{ + using value_type = T; + using size_type = std::size_t; + using propagate_on_container_move_assignment = true_type; + + constexpr allocator() noexcept = default; + constexpr allocator(const allocator&) noexcept = default; + + template + constexpr allocator(const allocator&) noexcept {} + + [[nodiscard]] constexpr T* allocate(size_t n) + { + if (numeric_limits::max() / sizeof(T) < n) + { + __ba_throw bad_array_new_length(); + } + return static_cast(::operator new(n * sizeof(T))); // TODO: alignment for bigger types + } + + constexpr void deallocate(T* p, size_t n) + { + (void) n; + ::operator delete(p); // TODO: bigger alignments + } +}; + constexpr void* align(std::size_t alignment, std::size_t size, void*& ptr, std::size_t& space) noexcept { if (space < size) { diff --git a/bastl/include/new b/bastl/include/new index 80bd0bb..0056249 100644 --- a/bastl/include/new +++ b/bastl/include/new @@ -7,7 +7,7 @@ namespace std { -class bad_alloc : public std::exception +class bad_alloc : public exception { public: bad_alloc() noexcept = default; @@ -15,6 +15,11 @@ public: const char * what() const noexcept override; }; + +class bad_array_new_length : public bad_alloc +{ + +}; } inline void* operator new(std::size_t, void* placement) noexcept diff --git a/bastl/include/stdexcept b/bastl/include/stdexcept index dec66cc..c6c4163 100644 --- a/bastl/include/stdexcept +++ b/bastl/include/stdexcept @@ -4,7 +4,7 @@ #if !defined(BAD_APPLE_OS_STDEXCEPT_INCLUDED) #define BAD_APPLE_OS_STDEXCEPT_INCLUDED -#include "exception" +#include namespace std { diff --git a/bastl/include/type_traits b/bastl/include/type_traits index 0cafa81..b119bbc 100644 --- a/bastl/include/type_traits +++ b/bastl/include/type_traits @@ -86,6 +86,24 @@ struct type_identity template using type_identity_t = type_identity::type; + +template +struct integral_constant +{ + using value_type = T; + using type = integral_constant; + + static constexpr T value = v; + + constexpr operator value_type() const noexcept { return v; } + constexpr value_type operator()() const noexcept { return v; } +}; + +template +using bool_constant = integral_constant; + +using true_type = integral_constant; +using false_type = integral_constant; } #endif // !defined(BAD_APPLE_OS_TYPE_TRAITS_INCLUDED) diff --git a/bastl/include/vector b/bastl/include/vector index 422851b..fbe318f 100644 --- a/bastl/include/vector +++ b/bastl/include/vector @@ -6,13 +6,14 @@ #include #include +#include #include #include #include namespace std { -template // TODO: allocator +template> class vector { public: @@ -29,9 +30,10 @@ private: T* _elements = nullptr; size_type _size = 0; size_type _capacity = 0; + Allocator _allocator = {}; public: constexpr vector() noexcept = default; - constexpr vector(const vector& other) noexcept + constexpr vector(const vector& other) noexcept : _allocator(other._allocator) { resize(other.size()); for (size_type idx = 0; idx < size(); ++idx) @@ -42,16 +44,22 @@ public: constexpr vector(vector&& other) noexcept : _elements(exchange(other._elements, nullptr)), _size(exchange(other._size, 0)), - _capacity(exchange(other._capacity, 0)) + _capacity(exchange(other._capacity, 0)), + _allocator(exchange(other._allocator, {})) { } - constexpr explicit vector(size_type count, const value_type& value = value_type()) + constexpr explicit vector(const Allocator& allocator) noexcept : _allocator(allocator) {} + constexpr explicit vector(size_type count, const value_type& value = value_type(), const Allocator& allocator = {}) : _allocator(allocator) { resize(count, value); } constexpr ~vector() noexcept { - delete _elements; + for (size_type idx = 0; idx < size(); ++idx) + { + _elements[idx].~T(); + } + _allocator.deallocate(_elements, _capacity); } constexpr vector& operator=(const vector& other) { @@ -302,7 +310,7 @@ private: if (capacity() == newCapacity) { return; } - T* newElements = static_cast(malloc(newCapacity * sizeof(T))); + T* newElements = _allocator.allocate(newCapacity * sizeof(T)); if (newElements == nullptr) { __ba_throw bad_alloc(); @@ -312,7 +320,7 @@ private: ::new (&newElements[idx]) T(move(_elements[idx])); _elements[idx].~T(); } - free(_elements); + _allocator.deallocate(_elements, _capacity); _elements = newElements; _capacity = newCapacity; } diff --git a/targets/_any/include/math.h b/targets/_any/include/math.h new file mode 100644 index 0000000..181b382 --- /dev/null +++ b/targets/_any/include/math.h @@ -0,0 +1,43 @@ + +#pragma once + +#if !defined(BAD_APPLE_OS_MATH_H_INCLUDED) +#define BAD_APPLE_OS_MATH_H_INCLUDED + +#if !defined(HUGE_VALF) +#define HUGE_VALF (__builtin_inff()) +#endif + +#if !defined(FLT_QNAN) +#define FLT_QNAN (__builtin_nanf("")) +#endif + +#if !defined(FLT_SNAN) +#define FLT_SNAN (__builtin_nansf("")) +#endif + +#if !defined(HUGE_VAL) +#define HUGE_VAL (__builtin_inf()) +#endif + +#if !defined(DBL_QNAN) +#define DBL_QNAN (__builtin_nan("")) +#endif + +#if !defined(DBL_SNAN) +#define DBL_SNAN (__builtin_nans("")) +#endif + +#if !defined(HUGE_VALL) +#define HUGE_VALL (__builtin_infl()) +#endif + +#if !defined(LDBL_QNAN) +#define LDBL_QNAN (__builtin_nanl("")) +#endif + +#if !defined(LDBL_SNAN) +#define LDBL_SNAN (__builtin_nansl("")) +#endif + +#endif // !defined(BAD_APPLE_OS_MATH_H_INCLUDED) diff --git a/targets/_any/include/os/memory.hpp b/targets/_any/include/os/memory.hpp index 1e887c3..d424b96 100644 --- a/targets/_any/include/os/memory.hpp +++ b/targets/_any/include/os/memory.hpp @@ -40,8 +40,8 @@ enum class MemoryType struct MemoryRange { - std::uint64_t pageBase; - std::uint64_t numPages; + std::uint64_t pageBase = 0; + std::uint64_t numPages = 0; MemoryType type = MemoryType::USABLE; MemoryRange& operator=(const MemoryRange&) noexcept = default; @@ -51,11 +51,31 @@ struct MemoryRange } }; +struct AllocatePagesOptions +{ + std::size_t numPages = 1; + bool bigPages = false; +}; + +struct PageRange +{ + std::uint64_t mBase = 0; + std::uint64_t numPages = 0; + + explicit operator bool() const noexcept { return numPages > 0; } + bool operator!() const noexcept { return numPages == 0; } + + [[nodiscard]] std::span getMemory() const noexcept + { + std::uint8_t* basePtr = std::bit_cast(mBase << 12); + return {basePtr, basePtr + (numPages * 512)}; + } +}; + [[nodiscard]] bool setupPaging(std::span memoryRanges) noexcept; [[nodiscard]] const char* memoryTypeName(MemoryType type) noexcept; -[[nodiscard]] void* allocatePages(unsigned numConsecutive) noexcept; -[[nodiscard]] inline void* allocatePage() noexcept { return allocatePages(1); } +[[nodiscard]] PageRange allocatePages(const AllocatePagesOptions& options = {}) noexcept; void setupIdentityPaging(std::uint64_t page) noexcept; void setupIdentityPaging2M(std::uint64_t page) noexcept; @@ -69,10 +89,16 @@ inline void identityMapRegion(void* start, std::size_t bytes) noexcept } template -inline T* pageToPointer(std::uint64_t page) noexcept +[[nodiscard]] inline T* pageToPointer(std::uint64_t page) noexcept { return std::bit_cast(page << 12); } + +[[nodiscard]] inline std::size_t bytesToPages(std::size_t bytes, bool bigPages = false) noexcept +{ + const std::size_t pageBytes = bigPages ? (2 << 20) : 4096; + return (bytes + pageBytes - 1) / pageBytes; +} } void __ba_initInitialHeap() noexcept; diff --git a/targets/_any/src/cstdlib/stdlib.cpp b/targets/_any/src/cstdlib/stdlib.cpp index 2196b3c..09920a6 100644 --- a/targets/_any/src/cstdlib/stdlib.cpp +++ b/targets/_any/src/cstdlib/stdlib.cpp @@ -2,6 +2,7 @@ #include #include +#include "os/memory.hpp" #include "os/tty.hpp" namespace @@ -33,18 +34,6 @@ void __ba_initInitialHeap() noexcept gNextBlock->nextBlock = nullptr; } -void __ba_registerAllocatableMemory(void* memory, size_t size) noexcept -{ - if (size < sizeof(max_align_t)) - { - return; - } - MallocBlock* newBlock = static_cast(memory); - newBlock->nextBlock = gNextBlock; - newBlock->elements = size / sizeof(max_align_t); - gNextBlock = newBlock; -} - extern "C" { void abort() @@ -94,7 +83,21 @@ void* malloc(size_t size) noexcept prevBlock = block; } - return nullptr; + baos::PageRange pages = baos::allocatePages({ + .numPages = std::max(1ul, baos::bytesToPages(size, /* bigPages = */ true)), + .bigPages = true + }); + if (!pages) { + return nullptr; + } + + std::span memory = pages.getMemory(); + MallocBlock* newBlock = std::bit_cast(memory.begin()); + newBlock->nextBlock = gNextBlock; + newBlock->elements = memory.size(); + gNextBlock = newBlock; + + return malloc(size); } void free(void* memory) noexcept diff --git a/targets/_any/src/os/memory.cpp b/targets/_any/src/os/memory.cpp index 2ef377c..9939965 100644 --- a/targets/_any/src/os/memory.cpp +++ b/targets/_any/src/os/memory.cpp @@ -188,7 +188,7 @@ bool allocateIdentityMappedPages(std::size_t numPages, std::size_t pageAlignment if (!allocateMemoryRange(numPages, pageAlignment, page)) { return false; } - setupIdentityPaging2M(page); + setupIdentityPaging(page, page + numPages); outPage = page; return true; } @@ -272,6 +272,27 @@ const char* memoryTypeName(MemoryType type) noexcept return ""; } +PageRange allocatePages(const AllocatePagesOptions& options) noexcept +{ + if (options.numPages == 0) { + return {}; + } + std::uint64_t page = 0; + const std::uint64_t numPages = options.numPages * (options.bigPages ? BIG_PAGE_SIZE : 1); + if (!allocateIdentityMappedPages( + /* numPages = */ numPages, + /* pageAlignment = */ options.bigPages ? BIG_PAGE_ALIGNMENT : 1, + /* outPage = */ page + )) + { + return {}; + } + return { + .mBase = page, + .numPages = numPages + }; +} + void setupIdentityPaging(std::uint64_t page) noexcept { PageTableEntry& pageTableEntry = getOrCreatePage(page);