Hello, I've fixed a few compilation errors with libstdc++v3 with AVR-Libc and was even able to use boost.spirit x3 with small patches to boost as well.
Attached is the patch. Please don't hesitate to ask modifications for upstream inclusion. Right now std::cout is not working (and just include'ing <iostream> makes the final executable 100k bigger), however being able to use all C++11 and C++14 goodies from the STL is already really great. Kind regards, -- Felipe Magno de Almeida
From 53952b274a4e4f4578bf4eb2332a7aa07b26a23b Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida <fel...@expertisesolutions.com.br> Date: Thu, 15 Sep 2016 15:54:50 -0300 Subject: [PATCH 1/3] Add #ifdef case for 16 bits in cow-stdexcept.cc Added #ifdef case for when void* is 16 bits so it compiles in AVR target. --- libstdc++-v3/src/c++11/cow-stdexcept.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/src/c++11/cow-stdexcept.cc b/libstdc++-v3/src/c++11/cow-stdexcept.cc index 31a89df..5b7f9ba 100644 --- a/libstdc++-v3/src/c++11/cow-stdexcept.cc +++ b/libstdc++-v3/src/c++11/cow-stdexcept.cc @@ -208,6 +208,8 @@ extern void* _ZGTtnaX (size_t sz) __attribute__((weak)); extern void _ZGTtdlPv (void* ptr) __attribute__((weak)); extern uint8_t _ITM_RU1(const uint8_t *p) ITM_REGPARM __attribute__((weak)); +extern uint16_t _ITM_RU2(const uint16_t *p) + ITM_REGPARM __attribute__((weak)); extern uint32_t _ITM_RU4(const uint32_t *p) ITM_REGPARM __attribute__((weak)); extern uint64_t _ITM_RU8(const uint64_t *p) @@ -272,12 +274,15 @@ _txnal_cow_string_C1_for_exceptions(void* that, const char* s, static void* txnal_read_ptr(void* const * ptr) { static_assert(sizeof(uint64_t) == sizeof(void*) - || sizeof(uint32_t) == sizeof(void*), - "Pointers must be 32 bits or 64 bits wide"); + || sizeof(uint32_t) == sizeof(void*) + || sizeof(uint16_t) == sizeof(void*), + "Pointers must be 16 bits, 32 bits or 64 bits wide"); #if __UINTPTR_MAX__ == __UINT64_MAX__ return (void*)_ITM_RU8((const uint64_t*)ptr); -#else +#elif __UINTPTR_MAX__ == __UINT32_MAX__ return (void*)_ITM_RU4((const uint32_t*)ptr); +#else + return (void*)_ITM_RU2((const uint16_t*)ptr); #endif } -- 2.9.3 From 24d0e86a560fc109298b8a530f04e2129ff613c6 Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida <fel...@expertisesolutions.com.br> Date: Thu, 15 Sep 2016 18:52:57 -0300 Subject: [PATCH 2/3] Use temporary int objects to access struct tm members Call _M_extract_* functions family through temporary int objects, so it doesn't convert from lvalue to rvalue through a temporary in AVR because of the incompatible types used in AVR-Libc. This fixes compilation errors with AVR-Libc while compiling libstdc++ for AVR target. --- libstdc++-v3/include/bits/locale_facets_nonio.tcc | 44 ++++++++++++++++------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc index 1a4f9a0..cc9d2df 100644 --- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc +++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc @@ -659,30 +659,38 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 // Abbreviated weekday name [tm_wday] const char_type* __days1[7]; __tp._M_days_abbreviated(__days1); - __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days1, + __tm->tm_wday = __mem; + __beg = _M_extract_name(__beg, __end, __mem, __days1, 7, __io, __tmperr); + __mem = __tm->tm_wday; break; case 'A': // Weekday name [tm_wday]. const char_type* __days2[7]; __tp._M_days(__days2); - __beg = _M_extract_name(__beg, __end, __tm->tm_wday, __days2, + __mem = __tm->tm_wday; + __beg = _M_extract_name(__beg, __end, __mem, __days2, 7, __io, __tmperr); + __tm->tm_wday = __mem; break; case 'h': case 'b': // Abbreviated month name [tm_mon] const char_type* __months1[12]; __tp._M_months_abbreviated(__months1); - __beg = _M_extract_name(__beg, __end, __tm->tm_mon, + __mem = __tm->tm_mon; + __beg = _M_extract_name(__beg, __end, __mem, __months1, 12, __io, __tmperr); + __tm->tm_mon = __mem; break; case 'B': // Month name [tm_mon]. const char_type* __months2[12]; __tp._M_months(__months2); - __beg = _M_extract_name(__beg, __end, __tm->tm_mon, + __mem = __tm->tm_mon; + __beg = _M_extract_name(__beg, __end, __mem, __months2, 12, __io, __tmperr); + __tm->tm_mon = __mem; break; case 'c': // Default time and date representation. @@ -693,18 +701,22 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 break; case 'd': // Day [01, 31]. [tm_mday] - __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 1, 31, 2, + __mem = __tm->tm_mday; + __beg = _M_extract_num(__beg, __end, __mem, 1, 31, 2, __io, __tmperr); + __tm->tm_mday = __mem; break; case 'e': // Day [1, 31], with single digits preceded by // space. [tm_mday] + __mem = __tm->tm_mday; if (__ctype.is(ctype_base::space, *__beg)) - __beg = _M_extract_num(++__beg, __end, __tm->tm_mday, 1, 9, + __beg = _M_extract_num(++__beg, __end, __mem, 1, 9, 1, __io, __tmperr); else - __beg = _M_extract_num(__beg, __end, __tm->tm_mday, 10, 31, + __beg = _M_extract_num(__beg, __end, __mem, 10, 31, 2, __io, __tmperr); + __tm->tm_mday = __mem; break; case 'D': // Equivalent to %m/%d/%y.[tm_mon, tm_mday, tm_year] @@ -715,13 +727,17 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 break; case 'H': // Hour [00, 23]. [tm_hour] - __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 0, 23, 2, + __mem = __tm->tm_hour; + __beg = _M_extract_num(__beg, __end, __mem, 0, 23, 2, __io, __tmperr); + __tm->tm_hour = __mem; break; case 'I': // Hour [01, 12]. [tm_hour] - __beg = _M_extract_num(__beg, __end, __tm->tm_hour, 1, 12, 2, + __mem = __tm->tm_hour; + __beg = _M_extract_num(__beg, __end, __mem, 1, 12, 2, __io, __tmperr); + __tm->tm_hour = __mem; break; case 'm': // Month [01, 12]. [tm_mon] @@ -732,8 +748,10 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 break; case 'M': // Minute [00, 59]. [tm_min] - __beg = _M_extract_num(__beg, __end, __tm->tm_min, 0, 59, 2, + __mem = __tm->tm_min; + __beg = _M_extract_num(__beg, __end, __mem, 0, 59, 2, __io, __tmperr); + __tm->tm_min = __mem; break; case 'n': if (__ctype.narrow(*__beg, 0) == '\n') @@ -752,11 +770,13 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 // Seconds. [tm_sec] // [00, 60] in C99 (one leap-second), [00, 61] in C89. #if _GLIBCXX_USE_C99 - __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 60, 2, + __mem = __tm->tm_sec; + __beg = _M_extract_num(__beg, __end, __mem, 0, 60, 2, #else - __beg = _M_extract_num(__beg, __end, __tm->tm_sec, 0, 61, 2, + __beg = _M_extract_num(__beg, __end, __mem, 0, 61, 2, #endif __io, __tmperr); + __tm->tm_sec = __mem; break; case 't': if (__ctype.narrow(*__beg, 0) == '\t') -- 2.9.3 From cfb0f8c760fdbc91aa23afcd767e1ba8533a1a84 Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida <fel...@expertisesolutions.com.br> Date: Thu, 15 Sep 2016 16:05:02 -0300 Subject: [PATCH 3/3] Enable libstdc++ compilation in AVR targets Enable libstdc++ compilation in AVR targets with AVR-Libc. Most float pointing math functions are already defined in AVR-Libc, so defines are in place to avoid multiple definition of these functions. --- libstdc++-v3/configure | 49 +++++++++++++++++++++++++++++++++++++++++++++ libstdc++-v3/crossconfig.m4 | 26 ++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 6332c4d..b970077 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -28830,6 +28830,55 @@ case "${host}" in # This is a freestanding configuration; there is nothing to do here. ;; + avr*-*-*) + $as_echo "#define HAVE_ACOSF 1" >>confdefs.h + + $as_echo "#define HAVE_ASINF 1" >>confdefs.h + + $as_echo "#define HAVE_ATAN2F 1" >>confdefs.h + + $as_echo "#define HAVE_ATANF 1" >>confdefs.h + + $as_echo "#define HAVE_CEILF 1" >>confdefs.h + + $as_echo "#define HAVE_COSF 1" >>confdefs.h + + $as_echo "#define HAVE_COSHF 1" >>confdefs.h + + $as_echo "#define HAVE_EXPF 1" >>confdefs.h + + $as_echo "#define HAVE_FABSF 1" >>confdefs.h + + $as_echo "#define HAVE_FLOORF 1" >>confdefs.h + + $as_echo "#define HAVE_FMODF 1" >>confdefs.h + + $as_echo "#define HAVE_FREXPF 1" >>confdefs.h + + $as_echo "#define HAVE_SQRTF 1" >>confdefs.h + + $as_echo "#define HAVE_HYPOTF 1" >>confdefs.h + + $as_echo "#define HAVE_LDEXPF 1" >>confdefs.h + + $as_echo "#define HAVE_LOG10F 1" >>confdefs.h + + $as_echo "#define HAVE_LOGF 1" >>confdefs.h + + $as_echo "#define HAVE_MODFF 1" >>confdefs.h + + $as_echo "#define HAVE_POWF 1" >>confdefs.h + + $as_echo "#define HAVE_SINF 1" >>confdefs.h + + $as_echo "#define HAVE_SINHF 1" >>confdefs.h + + $as_echo "#define HAVE_TANF 1" >>confdefs.h + + $as_echo "#define HAVE_TANHF 1" >>confdefs.h + + ;; + mips*-sde-elf*) # These definitions are for the SDE C library rather than newlib. SECTION_FLAGS='-ffunction-sections -fdata-sections' diff --git a/libstdc++-v3/crossconfig.m4 b/libstdc++-v3/crossconfig.m4 index 6abc84f..2b955ec 100644 --- a/libstdc++-v3/crossconfig.m4 +++ b/libstdc++-v3/crossconfig.m4 @@ -9,6 +9,32 @@ case "${host}" in # This is a freestanding configuration; there is nothing to do here. ;; + avr*-*-*) + AC_DEFINE(HAVE_ACOSF) + AC_DEFINE(HAVE_ASINF) + AC_DEFINE(HAVE_ATAN2F) + AC_DEFINE(HAVE_ATANF) + AC_DEFINE(HAVE_CEILF) + AC_DEFINE(HAVE_COSF) + AC_DEFINE(HAVE_COSHF) + AC_DEFINE(HAVE_EXPF) + AC_DEFINE(HAVE_FABSF) + AC_DEFINE(HAVE_FLOORF) + AC_DEFINE(HAVE_FMODF) + AC_DEFINE(HAVE_FREXPF) + AC_DEFINE(HAVE_SQRTF) + AC_DEFINE(HAVE_HYPOTF) + AC_DEFINE(HAVE_LDEXPF) + AC_DEFINE(HAVE_LOG10F) + AC_DEFINE(HAVE_LOGF) + AC_DEFINE(HAVE_MODFF) + AC_DEFINE(HAVE_POWF) + AC_DEFINE(HAVE_SINF) + AC_DEFINE(HAVE_SINHF) + AC_DEFINE(HAVE_TANF) + AC_DEFINE(HAVE_TANHF) + ;; + mips*-sde-elf*) # These definitions are for the SDE C library rather than newlib. SECTION_FLAGS='-ffunction-sections -fdata-sections' -- 2.9.3