65816-llvm-mos/runtime/include/c++/etl_profile.h
Scott Duensing da095402ec Updated
2026-06-02 23:17:57 -05:00

102 lines
5 KiB
C++

// etl_profile.h — ETL configuration for the W65816 / Apple IIgs target.
//
// Picked up by etl/platform.h via __has_include("etl_profile.h"). This
// file must live in the include path of any TU that uses ETL — buildGno.sh
// adds `-I runtime/include/c++` for that reason.
//
// Tells ETL: we have no STL, no exceptions, no threads, no atomics, and
// our int is 16-bit. ETL's own portable headers (etl/algorithm.h,
// etl/array.h, etl/vector.h, etc.) are substituted everywhere the upstream
// would have reached for <algorithm>/<array>/<vector>.
#ifndef ETL_PROFILE_W65816_H
#define ETL_PROFILE_W65816_H
// No host STL: <algorithm>, <type_traits>, <vector> etc. are not available.
// ETL_NO_STL routes ETL to its own equivalents for everything that doesn't
// strictly require a compiler-provided header.
#define ETL_NO_STL
// SJLJ exception machinery exists in the runtime, but pulling it in for
// every container operation would bloat unacceptably; default-off matches
// the upstream embedded convention. Programs that want try/catch still
// get it via clang's normal flags — this only stops ETL itself from
// throwing. (Define ETL_THROW_EXCEPTIONS at the TU level to opt back in.)
// (Nothing to define: omitting ETL_THROW_EXCEPTIONS is itself the off
// state, per platform.h L264-269.)
// Generic device, bare-metal — matches profiles/clang_generic_no_stl.h.
// The target is a 16-bit-int 65816 (clang's `w65816` triple) — no specific
// device profile.
#define ETL_TARGET_DEVICE_GENERIC
#define ETL_TARGET_OS_NONE
// Force ETL to use its own initializer_list shim instead of <initializer_list>.
// With ETL_NO_STL set above, ETL falls back to its bundled std::initializer_list
// definition; this define is belt-and-braces in case a future ETL revision
// changes the default.
#define ETL_FORCE_ETL_INITIALIZER_LIST
// No threads / no atomics — our runtime is single-threaded by construction.
#define ETL_NO_ATOMICS
// Force off any "compatibility with STL" surface ETL tries to emit that
// would call into std:: types we don't have. ETL_NO_STL above already
// gates most of this; ETL_NO_STD_OSTREAM avoids the iostream surface
// in to_string.h / format.h.
#define ETL_NO_STD_OSTREAM
// FP-format off by default (Phase 5.4). ETL's format.h pulls in <cmath>
// when FP formatting is enabled; we have the shim (runtime/include/c++/
// cmath) but the soft-double surface (sqrt/pow/exp/log + sprintf %g)
// blows past the single-bank text budget on most demos. Per Phase 0.5
// of the gap-closure plan the FP-enabled build is a separate `--layer2`
// target opted in at the TU level with `-UETL_FORMAT_NO_FLOATING_POINT`.
//
// ETL's platform.h derives ETL_USING_FORMAT_FLOATING_POINT from this
// switch (see platform.h L159-165): defined => 0/off, undefined => 1/on.
// Once you flip the gate ETL_USING_FORMAT_FLOATING_POINT becomes 1 and
// `format_to(buf, "{:.3f}", 3.14)` works at the cost of pulling in
// __mulsi3 / __divdf3 / __addsf3 / sqrt etc - measured at ~10-12 KB
// (Phase 5.4 step 5 size spike, demos/cxxStreamProbe).
#ifndef ETL_FORMAT_NO_FLOATING_POINT
#define ETL_FORMAT_NO_FLOATING_POINT
#endif
// ---- chrono clock duration overrides -------------------------------
//
// ETL's clocks.h defaults the three clock duration types to
// `etl::chrono::nanoseconds` when int is >= 32-bit, otherwise to
// `etl::chrono::milliseconds`. On the W65816 `int` is 16-bit, so we
// land on the milliseconds branch — but `etl::chrono::milliseconds`
// itself is `duration<int64_t, milli>` whenever ETL_USING_64BIT_TYPES
// is on (the default; turning it off would suppress i64 stdint types
// project-wide, which we don't want).
//
// i64 arithmetic on the W65816 is a string of libcalls (__addsi3 et al
// stitched into 64-bit add/sub/mul), so forcing the chrono rep to
// int32_t cuts every chrono::now() comparison/duration_cast down to a
// pair of 32-bit ops. Override the three documented config knobs to
// `duration<int32_t, etl::milli>` directly; this also makes
// `etl_get_*_clock()` return int32_t (the extern "C" hook signatures
// in clocks.h are derived from `<duration>::rep`).
#define ETL_CHRONO_SYSTEM_CLOCK_DURATION etl::chrono::duration<int32_t, etl::milli>
#define ETL_CHRONO_HIGH_RESOLUTION_CLOCK_DURATION etl::chrono::duration<int32_t, etl::milli>
#define ETL_CHRONO_STEADY_CLOCK_DURATION etl::chrono::duration<int32_t, etl::milli>
// ---- std:: forward declarations ETL needs to specialize ------------
//
// etl/tuple.h emits `template <typename...> struct std::tuple_size<...>`
// specializations unconditionally for ETL_NOT_USING_STL, but guards
// the corresponding *forward declarations* with a clang-version check
// that assumes clang >= 19 implies libc++ on disk (true for Apple
// Clang). We have neither — bare clang + no STL — so we provide the
// forward decls here so ETL's specialization references resolve.
#ifdef __cplusplus
#include <stddef.h>
namespace std {
template <typename T> struct tuple_size;
template <size_t Index, typename T> struct tuple_element;
}
#endif
#endif // ETL_PROFILE_W65816_H