MAEC TOOL NEWS:
MAECT-M3T-NC308WA_2-011116D
M3T-NC308WA, M3T-NC30WA, M3T-NC79WA, M3T-NC77WA
ご使用上のお願い
|
Cコンパイラ (アセンブラ・統合化開発環境付き) M3T-NC308WA, M3T-NC30WA, M3T-NC79WA, M3T-NC77WA の使用上の注意事項を連絡します。
- 標準ライブラリ "pow" 関数の不正な定義域エラーについて
- switch文を含むループに関する不正な最適化について
- ループ内でポインタ変数を更新する記述のコンパイル強制終了について
- 標準ライブラリpow関数の不正な定義域エラーについて
- 1.1 該当製品
- M3T-NC308WA V.1.00 Release 1 ~ V.2.00 Release 2
- M3T-NC30WA V.1.00 Release 1 ~ V.3.20 Release 2
- M3T-NC79WA V.1.00 Release 1 ~ V.3.20 Release 2
- M3T-NC77WA V.3.20 Release 1 ~ V.5.20 Release 4
- 1.2 内容
- 標準ライブラリの "pow" 関数を呼び出した場合、定義域内の値を引数に渡しているにも関わらず、定義域エラーが発生することがあります。
- 1.3 発生条件
- 以下2点の条件のいずれか1つを満たす場合に発生します。
- (1) 第一引数がゼロかつ第二引数が正である。
- (2) 第一引数が非ゼロかつ第二引数が負である。
- 1.4 発生例
-----------------------------------------------------------------------
#include <math.h>
#include <errno.h>
double ans1;
int func(void)
{
ans1 = pow(0.0, 5.0); /* 発生条件(1) */
if (errno == EDOM) return -1; /* 定義域エラー発生のチェック */
return 0;
}
-----------------------------------------------------------------------
- 1.5 回避策
- 製品に添付されているライブラリソースファイルを修正し、ライブラリを再作成して、ユーザプログラムをリンクし直してください。
なお、ライブラリの再作成方法の詳細については、ユーザーズマニュアルの 「E.3.2 入出力関数の変更手順 c. 変更したソースプログラムの組み込み」 を参照してください。
修正個所は、以下の通りです。
ライブラリソースファイル "pow.c" の "pow" 関数の最初のif文 (先頭から5行目前後)
[正] if ((x == 0 && y <= 0) || (x < 0 && y != (int)y)) {
[誤] if (x == 0 || y <= 0 || (x < 0 && y != (int)y)) {
- 1.6 恒久対策
- 本内容は、以下のバージョンでそれぞれ改修済みです。
- M3T-NC308WA V.3.00 Release 1
- M3T-NC30WA V.4.00 Release 1
- M3T-NC79WA V.4.00 Release 1
- M3T-NC77WA は、次期バージョンアップ時に改修する予定です。
M3T-NC308WA, M3T-NC30WA, M3T-NC79WA, M3T-NC77WA ご使用上のお願い
MAECT-M3T-NC308WA_2-011116D
- switch文を含むループに関する不正な最適化について
- 2.1 該当製品
- M3T-NC308WA V.1.00 Release 1 ~ V.3.10 Release 3
- M3T-NC30WA V.2.00 Release 1 ~ V.4.00 Release 2
- M3T-NC79WA V.2.00 Release 1 ~ V.4.10 Release 1
- M3T-NC77WA V.4.00 Release 1 ~ V.5.20 Release 4
- 2.2 内容
- M3T-NCxxWAコンパイラでは、"-OS"オプション指定時、ループ内にある不変式をループ前に移動させる最適化を実施しています。本最適化は、ループ内の条件分岐 (if文、switch文など) により実行されないことが有り得る経路上の式については適用できません。
しかし、switch文の分岐先での式について、誤ってループ前に移動してしまうことがあります。このとき生成されたコードは、実行しないかもしれない計算を必ず実行してしまいます。
- 2.3 発生条件
- 以下6点の条件をすべて満たす場合に発生することがあります。
- (1) コンパイル時に "-OS" オプションを指定している。
- (2) "-fST" オプションを指定している (M3T-NC79WA, M3T-NC77WAの場合)。
- (3) forまたはwhile文の中にswitch文が存在する。
- (4) 自動変数、レジスタ変数、または引数のいずれかが、caseラベルまたはdefaultラベルに分岐した先で更新されている。
- (5) (4)で変数に格納される値が、ループの反復実行によって変化しない。
- (6) コンパイルによって、(3)のswitch文が、分岐先テーブルによる間接分岐の命令列を生成する。
- 補足:
- 分岐先テーブルとは、命令中に埋め込まれた分岐先アドレスの並びです。
コンパイラは、分岐先テーブルの参照による間接分岐のほうが効率がよいと判断した場合、テーブルから分岐先アドレスを取得し間接分岐するコードを生成します。この判断は、switch文のcaseラベルのラベル数、値の範囲、連続性などに基づいて行われますが、機種により条件が異なります。
- 2.4 発生例
[C言語ソースファイル]
-----------------------------------------------------------------------
int func(void)
{
int i, a, flg = 0; /* 発生条件(4) 自動変数 flg を宣言 */
for (i = 0; i < 1; i++) {
switch (a) { /* 発生条件(3) */
case 8:
break;
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
default:
flg = 1; /* 発生条件(4),(5) この式が不正に移動される */
break;
}
}
return flg;
}
-----------------------------------------------------------------------
[M3T-NC308WAでのコンパイル結果の例(抜粋)]
-----------------------------------------------------------------------
mov.w #0000H,R0 ; i <== for文 の i = 0
mov.w -2[FB],R1 ; a
mov.w #0001H,-2[FB] ; flg <== 不正に移動されている
L0: <== 反復処理の先頭
sub.w #0008H,R1 ; minimum case
cmp.w #0009H,R1 ; case width check
jnc M2
mov.w #0008H,R1
M2:
indexwd.w R1
S1:
jmpi.w L16
L16: <== 分岐先テーブルの先頭
.word L7-S1&0ffffH
.word L7-S1&0ffffH
.word L7-S1&0ffffH
(以下略)
-----------------------------------------------------------------------
- 2.5 回避策
- 本現象が発生する反復処理の先頭に、ダミーの "asm" 関数を挿入してください。
[例]
-----------------------------------------------------------------------
for (i = 0; i < 1; i++) {
asm(); /* ダミーのasm();を挿入 */
switch (a) {
case 8:
break;
-----------------------------------------------------------------------
- 2.6 恒久対策
- 次期バージョンアップ時に改修する予定です。
M3T-NC308WA, M3T-NC30WA, M3T-NC79WA, M3T-NC77WA ご使用上のお願い
MAECT-M3T-NC308WA_2-011116D
- ポインタ変数を更新する記述のコンパイル強制終了について
- 3.1 該当製品
- M3T-NC308WA V.1.00 Release 1 ~ V.3.10 Release 3
- M3T-NC30WA V.3.10 Release 1 ~ V.4.00 Release 2
- M3T-NC79WA V.3.10 Release 1 ~ V.4.10 Release 1
- M3T-NC77WA V.5.10 Release 1 ~ V.5.20 Release 4
- 3.2 内容
- ポインタ変数によって間接参照した値に、そのポインタ自体を更新する処理を記述すると、コンパイルが強制終了することがあります。この場合、EWS版ではコアダンプが発生し、PC版では 「不正な処理を行いました」 などのメッセージが表示されます。
- 3.3 発生条件
- 以下4点の条件をすべて満たす場合に発生することがあります。
※ 条件をすべて満たす場合でも、現象が発生しないことがありますが、この場合に生成されたコードは問題ありません。
- (1) ポインタ変数で間接参照した値を、そのポインタ自体に書き込んでいる。
- (2) (1)のポインタ変数がレジスタに割り当てられている。
- (3) (1)のポインタを使用するfor文またはwhile文がある。
- (4) (3)と同じfor文またはwhile文の中に、間接参照がないと仮定すればループ外に移動できそうな不変式が存在する。
- 3.4 発生例
-----------------------------------------------------------------------
struct l {
unsigned int no;
struct l *next;
} *pp;
int func(void)
{
register struct l *p = pp; /* 発生条件(2) */
int i;
int n = 1;
int x = 0;
for (i = 0; i < n-1; i++) { /* 発生条件(4) "n-1" は不変式 */
if (p->no > (p->next)->no) x++; /* 発生条件(3) */
p = p->next; /* 発生条件(1) */
}
}
-----------------------------------------------------------------------
- 3.5 回避策
- 本現象が発生する反復処理の先頭に、ダミーの "asm" 関数を挿入してください。
[例]
-----------------------------------------------------------------------
for (i = 0; i < n-1; i++) {
asm(); /* ダミーのasm();を挿入 */
if (p->no > (p->next)->no) x++;
-----------------------------------------------------------------------
- 3.6 恒久対策
- 次期バージョンアップ時に改修する予定です。