ツールチェーン更新履歴

exeGCC と exeClang の相違点

注釈

SOLID-4.0 で RISC-V(RV32/RV64)をサポートする際、ツールチェーンをこれまでの GNU ベース(exeGCC)から LLVM ベース(exeClang)に変更しました。RISC-V は新規サポートターゲットなので exeGCC s007 以前は存在しませんが、ここでは AArch64/ARM の exeGCC s007 から見た時の、ターゲット非依存の変更点を解説します。(SOLID-5.0 から AArch64/ARM も exeClang になる予定です。)

exeGCC s007 と exeClang s008 の相違点は以下のようになります。

  • GNU(GCC/Binutils)のソフトウェアを廃止。標準 C ライブラリ以外を LLVM に変更

    • s007 まで

      • C/C++ コンパイラは GNU プロジェクトの GCC

        • Clang はコンパイラ・アセンブラ機能のみ使用(s007 から LLVM lld リンカにも対応)

      • アセンブラやリンカなどの ELF ツールは GNU プロジェクトの Binutils

      • コンパイラランタイムライブラリは GCC の libgcc (C++ 例外の実装を含む)

      • 標準 C++ ライブラリは GCC の libstdc++ (C++ ABI の実装を含む)

      • GNU make と KMC オリジナルの UNIX ツール(mv/cp など)を同梱

    • s008

      • C/C++ コンパイラとアセンブラは LLVM プロジェクトの Clang

      • リンカなどの ELF ツールは LLVM Tools

      • コンパイラランタイムライブラリは LLVM の compiler-rt

      • 標準 C++ ライブラリは LLVM の libc++

        • GCC の libstdc++ は内部に C++ ABI の実装( libsupc++ としても存在)を含んでおり、C++ 例外の実装は libgcc に含まれています。

        • LLVM の場合は C++ ABI の実装は libc++abi 、C++ 例外の実装は libunwind という独立したライブラリとして存在しています。これにより、例えば Clang で -stdlib=libstdc++ オプションを指定して GCC の libstdc++ を使用したり( libstdc++ + libunwind + compiler-rt のパターン)、あまり聞いたことはありませんが原理的には GCC の libgcc と組み合わせることも可能なはずです。( libc++ + libc++abi + libgcc のパターン)LLVM は GCC の後発であり、コンパイラ基盤(コンパイラをライブラリ化)を目指すプロジェクトなので、ここらへんはより洗練されていると感じます。

        • ただし exeClang の Clang はデフォルトが compiler-rt , libc++ , libc++abi , libunwind の設定でビルドされており、それ以外の組み合わせをサポートしません。

      • GNU make や mv/cp などの UNIX ツールは同梱されておりません。(単体販売していた exeGCC とは異なり、exeClang は SOLID の一部なので、基本的に SOLID-IDE から間接的に使用することになります。)

  • 言語規格を更新

    • s007 まで

      • gnu11/gnu++14

    • s008

      • gnu17/gnu++17

  • fat LTO オブジェクト サポート

    付属ライブラリ全てを -flto=thin -ffat-lto-objects オプション付きで コンパイルしています。これによって生成された *.o (ライブラリアーカイブ *.a 内部に含まれる) は LTO に必要な情報だけではなく機械語も含むため、 ファイルサイズは大きく(fat)なりますが、従来の ELF ファイル用ツールがそのまま使えるという利点があります。

  • 標準 C ライブラリの変更点

    exeGCC から引き続き NetBSD の libc/libm をベースにしています。exeClang から商用コンパイラテストツールを導入し、より標準規格との適合性を高めたため、変更点が他のバージョンの時よりも多くなっています。

    • ライブラリの仕様変更

      • exeGCC の伝統であった -fsigned-char の使用を廃止。

      • 数学ライブラリ(math.hcomplex.h)が errno を使用しなくなりました。

        これは C99 の math_errhandling == MATH_ERREXCEPT 仕様に準拠します。 この仕様の採用により、-fno-math-errno 最適化が可能となります。 (errno の使用は最適化を阻害しマルチスレッドとの相性が悪いため、現代的なツールチェーンの数学ライブラリでは使用されないのが一般的です。)

    以下は詳細となります。

    • math.h

      • サブノーマル領域のケアのため FreeBSD の logb(f) 関数に対するパッチを適用。

      • 精度の改善のため cbrt(f), scalbn(f), fmax(f/l), fmin(f/l) 関数に musl libc の実装を使用。

      • fmax(f/l), fmin(f/l) 関数の入力に NaN が来た時の挙動を仕様に合わせて修正。

      • C99 の math_errhandling サポート。

        • 値は常に MATH_ERREXCEPT になります。(MATH_ERRNO 未サポート。)

        • 例外が仕様通りに発生しない以下の数学関数を修正。

          cosh(f), exp(f), lgamma*(f), expm1(f), log1p(f)), acosh(f), atanh(f), nextafter(f)

    • C11 の uchar.h サポート(musl libc の実装を使用。)

      • uchar.h の関数を使用する場合は setlocale() による設定が必要です。

      • setlocale(LC_CTYPE, "") を実装。返る文字列は "C", "UTF-8", "cp932" のいずれかとなります。

      • setlocale(LC_CTYPE, locale) のlocaleに、例えばコンパイラのテストスイートのデフォルト値として指定されることが多い "en_US.UTF-8" など、部分文字列に有効なロケールが含まれている文字列を渡せるようになりました。

        • 有効な部分文字列(大文字小文字を区別しません)は以下になります。

          • "C" or "POSIX" (この2つは完全一致のみ。)

          • "NONE"

          • "UTF-8" or "UTF8"

          • "cp932" or "MSKanji"

        ただし、現在サポート(テスト)されているのは "C""UTF-8" のみです。"cp932" は exeGCC 時代の名残です。

    • ワイド文字関数の修正。

      • mbtowc(wchar *pwc, const char *s, size_t n)

        n が 0 の時 s を一切参照せずに -1 と EILSEQerrno)を返すように修正。

      • wint_t btowc(int c)

        入力値 c を unsigned char にキャストしてから判定していなかったのを修正。 btowc(x) == btowc((unsigned char)x) が成り立たなければいけない仕様ですが、c が 256 以上の場合不成立になっていました。(サポート対象外の cp932(Shift_JIS)は未確認です。)

      • mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps)

        前回の戻り値が -2 でリスタートした際、s == NULL の場合常に ps を初期化して成功していたのを修正。 リスタート時は s == NULL の場合 -1 と EILSEQerrno)を返すようになりました。

      • strftime()/wcsftime() の C99 で追加された仕様を実装。

        %g %G %V の実装に musl libc のコードを使用。

      • wctrans()"tolower" または "toupper" を渡した時に仕様通りに動作しない不具合を修正。

    • soft float時の fenv.h 関数が、errno と同様にマルチスレッド対応が可能になりました。また、デフォルトのシングルスレッドのみ対応の実装(source/errno.c)内の変数が増えたので一つの構造体にまとめました。

    • *scanf%n を実行するたびに戻り値が 1 増えていたバグを修正。

    • *snprintf のバッファサイズが足りない場合に %n の結果が正しくないバグを修正。

    • sys/_vlink_syscalls.h の関数プロトタイプに、上位関数に合わせて const 付与。関連するソースコードを修正。

    • stderr/stdout への出力時に改行コード LF を CRLF に変換していたのを廃止。

    • 浮動小数点数演算エミュレーションライブラリを SoftFloat-2a から 2c にアップデート。

      NetBSD が libc ソースツリー内で保守している 2a 版は、既に 2c までの修正パッチの大半が当たっているため、動作は変わりません。このアップデートは RISC-V の開発中に問題が発生し、NetBSD が行った修正差分を調査しようとした際に 2a 版が既に公式サイトからダウンロードできなくなっており、問題の切り分けと今後の保守のために行いました。

  • 標準 C++ ライブラリの変更点

    標準 C++ ライブラリは GCC の libstdc++ から LLVM の libc++ に変わりました。後発の libc++ は既に C++ 規格で廃止が決定している以下のヘッダと関数を実装していないため、コンパイルエラーとなります。

    cstdalign (C++20 で廃止。)

    memory のガベージコレクション用関数。(C++23 で廃止。)

    • std::declare_reachable

    • std::undeclare_reachable

    • std::declare_no_pointers

    • std::undeclare_no_pointers

    • std::get_pointer_safety

    • std::pointer_safety

ツールチェーン更新履歴(ARM)

s007

s006 の 64-bit 化とバグ修正アップデート。

  • 実行ファイルが 64-bit(x64)exe になりました。

    • Clang 4.0 と 6.0 はサポート終了。(Clang 12.0 のみ。)

    • solidelf.exe(32 bit)を削除。solidelf64.exe(64 bit)を solidelf.exe にリネーム。

    • libelf を依存関係(gnu/EXEGCC_GNU_SOFTWARE_INFO.txt)から除外。(readme 未記載。)

      libelf の更新が長年止まったままとなっていて、s007 のビルド環境 Ubuntu 20.04 LTS でビルドができなくなりました。そこで exeGCC のビルドシステムから除外したのですが、問題なく s007 がビルドできました。調査の結果 2010-11-03 PR lto/46273 で依存関係から削除されたようで、exeGCC for SOLID の全てのバージョンの GCC で不要だったことがわかりました。

  • LLD サポート(LLVM Linker 17.0.1 追加)。

    • LLD(LLVM Linker)サポートのためリンカスクリプト修正。

  • crt.o_kmc_start1() (ROM-RAM コピー完了前なのでライブラリ関数は使用できない)で最適化により memset() 呼び出しが発生していたのを修正。

  • libc

    • NetBSD 9.1 -> 9.3 ベースにアップデート。

      以下の 2 ファイルにわずかな修正のみ。

      • math.h (コメント修正のみ。)

      • source/stdio/fread.c

    • 日本語コメントの文字コード変換エラーでライブラリがリビルドできない不具合を修正。

    • locale 周りで不正メモリアクセスが発生する不具合を修正。

      locale は "C" 固定という仕様なので、これまで setlocale() などは十分にテストされていませんでした。

    • exit() で libc 内部の mutex を destroy するように修正。 (_libc_destroy() 追加。)

    • Clang で tgmath.h を使用するとコンパイルエラーになるのを修正。

    • complex.h で C11 CMPLX* マクロをサポート。

    • stdio.hfgetpos()/fsetpos()extern "C" 漏れを修正。

    • exit()_Exit() が weak シンボルになっていなかったのを修正。

    • シングルスレッドで _xfer = 0 の場合(デバッグ時、またはシミュレータで実行時)TLS 変数をサポート。

      単純に .tdata のアドレスを tp にセットし、.tbss 領域を 0 クリアするだけの対応です。

      TLS 変数はほとんど使われないと仮定し、本来 .bss と同様に NOLOAD でメモリは確保されない .tbss にメモリ領域を割り当てています。

      .sdata.data セクション内に配置するようにリンカスクリプトを修正。

  • ARM のみ

    • 一部ターゲットで __aeabi_memclr4()/__aeabi_memclr8() がリンクエラーになるのを修正。

    • 内部的な修正

      コンパイラのテスト用 rdimon サポートルーチンが qemu-system-(arm|aarch64) で正しく動作するようになりました。

    • libc_tiny

      bsearch() が全く正しく動作していない不具合を修正。

  • 既知の問題

    もともと C++17 はサポート範囲外ですが、std::aligned_alloc() を使用するとコンパイルエラーが発生します。

    • ARM のみ

      float ABI が hard の時、fma()/fmaf() に NEON の vmla.f64/f32 命令を使用するので、この命令が使用できないターゲットでは動作しません。(s006/s007 同梱 readme 未記載。)

s006

  • ソフトウェアアップデート

    • Clang 6.0.0 -> 12.0.1

    • GCC 6.4.0 -> 10.3.0

      • GMP 6.1.2 -> 6.2.1

      • MPFR 4.0.1 -> 4.1.0

      • MPC 1.1.0 -> 1.2.1

      • libiconv 1.15 -> 1.16

    • binutils 2.28.1 -> 2.36.1

    • GDB 8.1 -> 10.2

      • termcap 1.3.1

      • GNU make 4.2.1

  • GCC 10 と Clang 12 の変更点

    • -fno-common がデフォルトになりました。

      https://gcc.gnu.org/gcc-10/porting_to.html

      これまでと同じ動作にしたい場合は -fcommon を指定してください。

    • Clang 12 のデフォルトの C 言語標準規格は C17 ですが、C17 は C11 の マイナーアップデートであるため、GCC 10 デフォルトの C11 とは 互換性があります。 C++ はどちらも C++14 です。 C も C++ もデフォルトで GNU 拡張が有効です。

      -std=gnu11 or -std=gnu++14

    • GCC 10 で増えた以下のヘッダは Clang では未サポートとなります。

      • arm_bf16.h

      • arm_cde.h

      • arm_cmse.h

      • arm_fp16.h

      • arm_mve.h

      • arm_mve_types.h

  • 新規サポートターゲット

    • Cortex-M3 (ARMv7-M)

    • Cortex-R4(F)/R52(F) (ARMv7-R / VFPv3)

  • libc: NetBSD 7.0 -> NetBSD 9.1.

    NetBSD の libc は枯れているので、既存の部分はほとんど変わっていません。 7.0 では C11 対応が甘かったため、KMC が独自に実装したり、バグやコンパイル エラーを修正していたものの大半が 9.1 では修正されていたので、リベース。

    • 新規サポート関数

      • math.h

        fma(), fmaf()

      • 非標準関数(サポート外)

        • stdio.h

          open_memstream()

          open_wmemstream()

        • stdlib.h

          reallocarr()

          reallocarray()

          strtonum()

        • string.h

          strchrnul()

          strnstr()

          wcsnlen()

    • perror()/strerror()/strerror_r() に不正なエラー番号が渡された場合に不正メモリアクセス が発生するのを修正。

    • asctime()/strftime() に不正な struct tm が渡された場合に不正メモリアクセス が発生するのを修正。また asctime_r() に不正な struct tm が渡された場合、 通常の 26 文字以上のバッファが使用される可能性がある(最大 68 バイト) ので、struct tm の内容をチェックするか、十分に大きなバッファを渡して ください。

    • errno.hperror()/strerror()/strerror_r() の不整合を修正。

    • FAST_SPEED マクロを廃止。

    • libstdc++ の ostringstream に浮動小数点数を渡して文字列に変換しようと すると std::setlocale(LC_NUMERIC, 0) が NULL を返し、NULL 参照が発生して 例外が発生する不具合を修正。同様の問題を防ぐため setlocale() は常に "C" を返すように修正(一切 current locale を変更しません)。

    • osemu.h を非公開に変更。(source/ 以下に移動。)

    • kwin32.h を公開ヘッダに変更。(sys/_vlink_syscalls.h

  • libc_tiny

    • SSP 有効時に gets() のエイリアス __gets() が存在しないためリンクエラーになる 不具合を修正。

    • (v)snprintf(buf, n, ...)buf に NULL、または n0 が渡された場合に 不正メモリアクセスが発生するのを修正。

    • scanf() 系関数の [(^)文字集合] 書式を使用するとスタックオーバーフローが発生する 不具合を修正。

  • libcompiler_rt

    • *vfp 関数が hard/softfp のライブラリ中に存在しない不具合を修正。 (s004、s005 でリグレッション。)

      この関数はライブラリ仕様には存在しますが、おそらく実際には使用されないので 影響は無いと思われます。

  • 非互換性

    • セットアップツールから以下の define を削除。

      __USE_VFP, __MSL_NO_IO_SUPPORT__, __$GCC_CPU$__

s005

  • armcc に似た stdio 等の排他制御スタブを実装しました。

    • libgcc の一部にも使用されます。

    • 詳細は source\mutex_stub.c を参照してください。

  • SOLID の DLL をサポート。

    • 位置独立な libXXX_s.a ライブラリ、specs ファイル、リンカスクリプトを追加。

    • s は shared の意味で、Linux などでは libgcc_s.so のような拡張子になりますが

    • SOLID の DLL では static link なので .a です。

  • SOLID IDE のためのファイルを追加。(platform/

  • libc

    • __aeabi_memset()__aebi_memset() と typo していたバグを修正。

    • localtime()/localtime_r()tm_mdaytm_yday のバグを修正。

    • C11 の aligned_alloc() を追加。

    • GNU sed を追加し、makefile を簡略化。

  • misc

    • man/library_overview_ja.xls.xlsx 形式に変更。

    • bin/gnu_demangle(64).dll を削除。

    • ctime()/gmtime()/localtime()/mktime()/utime() のエラーハンドリングを修正。

    • random_deviceruntime_error を修正(生成するのは疑似乱数なので仕様的には変わらず未サポートとなります。)

    • Clang の内部的な変更。(IDE 内部でのみ使用。)

  • ベアメタル環境対応のための新規ターゲットサポート

    • Cortex-M4/M4F (ARMv7-M / FPv4-SP-D16-M)

    • Cortex-M7/M7F (ARMv7-EM / FPv5-DP-D16-M)

    • Cortex-R5/R7/R8 (ARMv7-R)

  • 省メモリ環境向けのコンパクトな libc、libc_tiny をサポート。

    • 制限

      • C89 までサポート。

      • ASCII のみ。

      • wchar 未サポート。

      • locale は "C" のみ。

      • VLINK(stdio.h)はあくまでもデバッグ用でマルチスレッド未サポート。

      • malloc は簡素な K&R malloc で、メモリが断片化するほどの頻繁 な使用は想定していません。

      • C++ を使えるような環境に向けたものではないので、非推奨。

      • libc と libgcc 以外のライブラリとの互換性は保たれています。(上記サポート仕様外の関数はダミー実装で正常動作しません。)

    • 使用方法

      • コンパイル時に -D_USE_LIBC_TINY を指定。

      • リンク時に -specs=$GCCDIR\lib\$GCC_DEFAULT\tiny.specs を指定。

      • 明示的に指定する場合のライブラリ名は libc_tiny.alibgcc_tiny.a-lc_tiny -lgcc_tiny

s002

  • ソフトウェアアップデート

    • GCC 4.9.4 -> 6.4.0

      • GMP 6.1.2

      • MPFR 3.1.5 -> 4.0.1

      • MPC 1.0.3 -> 1.1.0

      • libiconv 1.14 -> 1.15

    • binutils 2.27 -> 2.28.1

    • GDB 7.12.1 -> 8.1

      • termcap 1.3.1

    • GNU make 4.2.1

    • Clang 4.0.0 -> 6.0.0

  • C は gnu11、 C++ は gnu++14 規格がデフォルトになりました。(GCC 4.x までは gnu89、gnu++98 がデフォルト。)

  • 列挙型が 32 bit 固定になりました。( -fno-short-enums

  • -mfloat-abi=hard をサポートしました。

  • fstat()fd として stdin/stdout/stderr を渡した時にメモリアクセス違反が発生する不具合を修正しました。

    fwrite() など、fstat() を内部で使用する stdio.h のファイル関連関数にも影響があります。)

  • time.h

    • 欠けていた標準関数を実装しました。

    • 未サポートの関数をヘッダからコメントアウトしました。

    • time_t の開始年を DOS Time (1980) から UNIX Time (1970) に変更しました。

    • stat(), fstat(), lstat(), utime() のタイムスタンプ(秒の値)が正しくない不具合を修正しました。(MS-DOS 形式の秒の値は 2 で割った値でした。)

  • stdout が常にバッファリングされてしまい '\n' が来ても fflush() されない不具合を修正しました。

  • stdio が常にリンクされコードサイズが肥大してしまう不具合を修正しました。

    • dlmalloc の malloc_stats()fprintf() を使用するため廃止されました。

    • abort() 内部の fprintf()write() に置き換えました。

    • write() 内部の printf() を削除しました。

    • stdio を使用する ssp ライブラリを libc から分離しました。

  • 不要な関数、データの削除

    • VLINK 有効時

      • ファイルの最大 open 数 (_FD_MAX) を 100 から 20 に削減しました。

      • _LF_flg を廃止しました。ロングファイルネームサポートは常に有効です。

        (変数自体は残っているので既存の crt との互換性は保たれています。)

      • その他(内部実装)

  • arm_neon.h を Clang で使用するとエラーになる問題を修正しました。

  • 整数型のみサポートする *iprintf/*iscanf 関数を追加しました(newlib 拡張)

    詳細は stdio.h を参照してください。

    ただし、これは C99 までの仕様をフルサポートするため、スタック消費量がほとんど変わらず、内部で malloc() も使用するため、省メモリ環境においては SOLID が提供する同名の機能制限版関数の使用を推奨します。(SOLID とは別に、newlib との互換性のために追加された関数。)

s001

最初のリリース。

ツールチェーン更新履歴(AArch64)

基本的には ARM 版と同じなので、差分のみを記載します。

詳細は readme を参照してください。

s007

  • .data.bss が 4GB を超えるアドレスに配置された場合に VLINK が動作しない不具合を修正。

  • libgcc の一部のアセンブラ実装の関数が .bss の変数を使用するため、.text.bss が 4GB 以上離れるとリンクエラーになる問題を修正。

  • string.h

    ARM optimized routines v23.01 にアップデート。

    https://github.com/ARM-software/optimized-routines/releases/tag/v23.01

    変更点は strcpy() の最適化のみ。

s006

s005

  • ARM s005 とバージョン番号とソースツリーを統一。

    そのため AArch64 の s004 はスキップされ存在しません。

  • libc

    • memmove() のアセンブラコードが large code model 未対応だったのを修正。

  • libc_tiny

    AArch64 は libc_tiny(省メモリ環境向けのコンパクトな libc)をサポートしません。

s003

  • large code model をサポート。

  • Clang の内部的な修正。(生成コードに変化はありません。)

s002

最初のリリース。

ARM 版とバージョン番号を統一したため、AArch64 の s001 は存在しません。

ツールチェーン更新履歴(RISC-V)

s008

最初の exeClang リリース。「SOLID ツールチェーン」という括りなので、AArch64/ARM の exeGCC からバージョン番号を引き継ぎました。