exeGCC for SOLID s002 (ARM) ライブラリ仕様
本文章は s007 のリリース時に、遡ってアップデートされました。後から判明した機能制限(未実装)など、s002 リリース当時のドキュメントには記載されていない情報も含まれています。
ライブラリの共通設定
全てのライブラリは以下の設定でビルドされています。
char
型は signed。(-fsigned-char
)列挙型は 4 または 8 バイト。(
-fno-short-enums
)aligned data access。(
-mno-unaligned-access
)
C11/C++14 標準関数サポート
libc と libm は NetBSD-7.0 ベース
注釈
非標準の関数や BSD 独自の関数は、過去の exeGCC との互換性やライブラリ内部で使用している等の理由により存在していますが、サポート範囲外となります。もし必要な場合は自己責任で使用してください。ヘッダには存在しますが、実体が存在しない関数も多数あります。
KMC による標準関数の実装
abort()
,exit()
,perror()
,setjmp()
,longjmp()
,strerror()
,strerror_r()
,signal()
,raise()
time.h
clock()
,difftime()
,mktime()
,time()
,asctime()
,ctime()
,ctime_r()
,gmtime()
,localtime()
,localtime_r()
,strftime()
time_t
は 64 bit です。clock()
はダミー実装です。初回の呼び出しは必ず 0 になり、2 回目以降は 10msec 精度カウンタの前回呼び出し時との差分を返します。time_t
はうるう秒未考慮です。タイムゾーン未考慮(UTC のみ、常に GMT=UTC)なため、デバッグ時のみご利用ください。
malloc
,free
,realloc
,calloc
は dlmalloc 2.8.6 を使用しています。
VFP/FPU が有効なターゲットは RunFast モードで浮動小数点数演算を行います。
注釈
これはライブラリのビルド設定ではなく、exeGCC 付属のスタートアップルーチンの設定です。SOLID は自前のスタートアップルーチンを使用するため無関係となります。
付属のスタートアップルーチンでは RunFast モードを選択しています。これによりパフォーマンスが向上します。
RunFast モードは以下のような設定となります。
flush-to-zero モード(FTZ)
非正規数やアンダーフローを 0 に丸めます。NEON 命令は常にこの FTZ モードです。
デフォルト NaN モード(DN)
IEEE754 仕様では指数部が全て 1 で仮数部が 0 以外の任意のビットパターン(値)を NaN として扱います。そして NaN が入力された場合、その値を結果にそのまま伝搬します。一方 DN モードでは NaN が入力されたり演算結果が NaN になった場合、デフォルトの NaN 値を返します。デフォルト NaN のビットパターンはハードウェアの実装依存となります。NEON 命令は常にこの DN モードです。
浮動小数点数例外は発生しません。
数学関数のエラーは
errno
で判定します。
ロケールは
"C"
のみサポート*_l
(locale) 関数は、対応する_l
の無い関数と同じ挙動となります。
OS の機能を使用するような関数は、VLINK 有効時のみサポート
signal.h
はダミー関数です。signal()
,raise()
__SOFTFP__
時fenv.h
feraiseexcept()
は例外を発生させません。stdio.h
のprintf()
やファイル関係の関数、tmpnam()
など。stdlib.h
のgetenv()
,setenv()
など。system()
は未サポート。time.h
のclock()
,time()
,utime()
以下の非標準関数(KMC による実装)
rename()
,getcwd()
,getwd()
,open()
,creat()
,close()
,lseek()
,read()
,write()
,unlink()
,tell()
,dup()
,dup2()
,access()
,chdir()
,rmdir()
,findfirst()
,findnext()
,stat()
,fstat()
,lstat()
,mkdir()
,chmod()
,mktemp()
,sleep()
,usleep()
stat()
,fstat()
,lstat()
,utime()
の制限MS-DOS Data and Time (
FILETIME
) を使用しているので、保証されるのは 1980/1/1-2107/12/31 の範囲です。usleep()
の制限millisecond 精度です。
未サポートの機能
GCC の
float.h
の制限でFLT_ROUNDS
は常に 1 (nearest) となります。fenv.h
のfegetround()
で現行の丸めモードを取得してください。long double
math.h
,complex.h
ヘッダの*l
関数など。例:
long double sinl(long double x)
nexttoward()
,nexttowardf()
,nexttowardl()
C99
math.h
fma()
,fmaf()
FP_FAST_FMA
,FP_FAST_FMAF
,math_errhandling
,MATH_ERRNO
,MATH_ERREXCEPT
C11
uchar.h
time.h
struct timespec
,timespec_get()
stdio.h
fopen()
mode"x"
Remove
gets()
Annex F/G/K/L [Optional]
stdlib.h
aligned_alloc
(s002 readme 未記載。)C++11
random
ヘッダrandom_device
マルチスレッド
C11
stdatomic.h
,thread.h
ヘッダ [Optional]C++
auto_ptr
は C++11 以降非推奨のため未サポート扱いC++11
atomic
,thread
,mutex
,future
,condition_variable
ヘッダshared_ptr
はスレッドアンセーフC++14
shared_mutex
ヘッダweak_ptr
の lock() はスレッドアンセーフTLS (Thread Local Storage)
GCC 拡張の
__thread
, C11 の_Thread_local
, C++11 のthread_local
キーワード
PCH (PreCompiled Header)
LTO (Link Time Optimization)
ワイド文字(列)の扱いについて
ワイド文字型 wchar_t
は 4 バイト(UTF-32 LE)です。(GCC/Clang の仕様)
C11 の uchar.h
は未サポートです。
ワイド文字列リテラル L"..."
と C11 の U"..."
は同じ意味となり、-fexec-charset
オプションによる文字集合指定とは無関係に、必ず UCS4 (Unicode) コードポイントの配列になります。
注釈
つまり、仮に -fexec-charset=cp932
を指定したとしても、JIS X 0208 のコードポイント配列にはならないため、ワイド文字列リテラルをソースコード中に直接記述することはできません。これは GCC の仕様です。Clang はそもそも -finput-charset/-fexec-charset
オプション未サポートなので、常に UCS4 文字集合を UTF-8/32 エンコーディングで扱う仕様となります。
ライブラリがサポートするロケールは "C"
のみですが、マルチバイト文字列(mbs
)とワイド文字列(wcs
)を変換する際に必要となる、LC_CTYPE
のみ、"C"
, "utf-8"
, "cp932"
が指定可能です。デフォルトの LC_CTYPE
は "C"
となります。UTF-8(ASCII の範囲外の文字)を使用する場合は setlocale(LC_CTYPE, "utf-8")
呼び出しが mbs
/wcs
系関数を呼び出す前に必要です。
ワイド文字列からマルチバイト文字列への変換サンプル:
#include <locale.h> /* setlocale */
#include <stdlib.h> /* wcstombs */
/* ... */
wchar_t wcstr[] = L"この文字列は UCS4 文字集合を UTF-32 LE エンコーディングしたものとなります。";
int result;
char utf8buf[256];
/* 確認のため SOLID OS の syslog を使用します。 */
syslog_msk_log(LOG_UPTO(LOG_INFO), LOG_UPTO(LOG_INFO));
result = wcstombs(utf8buf, wcstr, 256);
/* デフォルトの "C" = ASCII 範囲外の文字を含むため失敗します。*/
if (result < 0) {
syslog(LOG_INFO, "XFAIL: please setlocale()");
}
/* utf-8 に設定します。*/
syslog(LOG_INFO, "setlocale:%s", setlocale(LC_CTYPE, "utf-8"));
/* UTF-32 LE -> UTF-8 */
result = wcstombs(utf8buf, wcstr, 256);
if (result < 0) {
syslog(LOG_INFO, "FAIL");
} else {
syslog(LOG_INFO, "SUCC: %s", utf8buf);
}
TeraTerm (UTF-8) での出力例:
XFAIL: please setlocale()
setlocale:UTF8
SUCC: この文字列は UCS4 文字集合を UTF-32 LE エンコーディングしたものとなります 。