ツールチェーン更新履歴
exeGCC と exeClang の相違点
注釈
SOLID-4.0 で RISC-V(RV32/RV64)をサポートする際、ツールチェーンをこれまでの GNU ベース(exeGCC)から LLVM ベース(exeClang)に変更しました。RISC-V は新規サポートターゲットなので exeGCC s007 以前は存在しませんが、ここでは AARCH64/ARM の exeGCC s007 から見た時の、ターゲット非依存の変更点を解説します。
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.h、complex.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 と
EILSEQ(errno)を返すように修正。
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 とEILSEQ(errno)を返すようになりました。
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その他
付属ライブラリのデバッグ情報に埋め込まれるファイルパスのルートディレクトリを
/KMC/exeClang/<ARCH>に統一しました。<ARCH>はaarch64,arm,riscv32,riscv64のいずれかになります。(exeGCC ではツールチェーンをビルドした際のファイルパスが埋め込まれていました。)
ツールチェーン更新履歴(exeClang 共通)
exeClang からサポートアーキテクチャが AARCH64/ARM/RISC-V の 3 種類になり、個別に記載すると煩雑になるため、共通の変更点をここにまとめて記載します。
s009
SOLID-5.0 から AARCH64/ARM は exeClang s009 になりました。(s008 は存在しません。)ここでは RISC-V の exeClang s008 から見た時の、AARCH64/ARM/RISC-V 共通の変更点を解説します。
標準 C ライブラリ(libm)の変更点
nan(),nanf()にNULLを渡した時 NULL 参照バグが発生するのを修正。C99 仕様では strtof/d("NAN", (char**)NULL) を返します。
remquo(),remquof()の quotient の符号が正しくない不具合を修正。(FreeBSD のパッチを適用。)C99 仕様では
remquo*(x, y, quotient)の quotient はx/yと同じ符号になります。
ツールチェーン更新履歴(ARM)
s009
ツールチェーンが exeClang になりました。
exeGCC と exeClang の相違点 および ツールチェーン更新履歴(共通)s009 を参照してください。
exeGCC s007 時代に検討していたライブラリ仕様変更 を全て採用しました。
GCC サポートの廃止。
char は unsigned char(ARM のデフォルト)に変更。
文字コードは UTF-8 のみサポート。
-fno-math-errno前提。RunFastMode の FTZ モードと DN モードを無効。
付属ライブラリの命令セットは thumb2 のみサポート(ARM のみ)
ARM 命令版の付属ライブラリは廃止されました。
注釈
SOLID がサポートする全ての ARM アーキテクチャにおいて、ARM と thumb2 はリンク互換性があるので、既存の ARM アセンブラコード資産は exeClang でも問題なく活用できます。
以下の新規ターゲットをサポート(ARM のみ)
ARMv8-R (-march=armv8-r / -mfpu=fp-armv8)
ARMv8-M Mainline (-march=armv8-m.main / -mfpu=fp-armv8-fullfp16-sp)
ARMv8.1-M Mainline (-march=armv8.1-m.main / -mfpu=fp-armv8-fullfp16-sp)
LLD で以下の警告が出ることがあったので、リンカスクリプトを修正(ARM のみ)
arm-kmc-eabi-ld.lld: warning: address (0xXXXXXXXX) of section .bss is not a multiple of alignment (16)制限事項(ARM のみ)
FPU の種類が多い R や M プロファイルで、
objdump -dコマンドの逆アセンブル結果が正しくない場合があります。その場合は、--mcpu=cortex-m55のようにオプションで CPU を指定してください。
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で C11CMPLX*マクロをサポート。stdio.hのfgetpos()/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=gnu11or-std=gnu++14)GCC 10 で増えた以下のヘッダは Clang では未サポートとなります。
arm_bf16.harm_cde.harm_cmse.harm_fp16.harm_mve.harm_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.hfma(),fmaf()非標準関数(サポート外)
stdio.hopen_memstream()open_wmemstream()stdlib.hreallocarr()reallocarray()strtonum()string.hstrchrnul()strnstr()wcsnlen()
perror()/strerror()/strerror_r()に不正なエラー番号が渡された場合に不正メモリアクセス が発生するのを修正。asctime()/strftime()に不正なstruct tmが渡された場合に不正メモリアクセス が発生するのを修正。またasctime_r()に不正なstruct tmが渡された場合、 通常の 26 文字以上のバッファが使用される可能性がある(最大 68 バイト) ので、struct tmの内容をチェックするか、十分に大きなバッファを渡して ください。errno.hとperror()/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、またはnに0が渡された場合に 不正メモリアクセスが発生するのを修正。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_mdayとtm_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_deviceのruntime_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.aとlibgcc_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 を参照してください。
s009
s007
.dataや.bssが 4GB を超えるアドレスに配置された場合に VLINK が動作しない不具合を修正。libgcc の一部のアセンブラ実装の関数が
.bssの変数を使用するため、.textと.bssが 4GB 以上離れるとリンクエラーになる問題を修正。string.hARM 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)
s009
ツールチェーン更新履歴(共通)s009 を参照してください。
s008
最初の exeClang リリース。「SOLID ツールチェーン」という括りなので、AARCH64/ARM の exeGCC からバージョン番号を引き継ぎました。