現象:
unsigned char/short型変数を含む式が同一関数内で、A−B、B−A(A,B:当該変数を含む式)と同時に存在する場合、共通式削除の最適化により不当に拡張命令を削除する場合があります。
[例] unsigned short var_a, var_b, var_c; long result; void f() { unsigned short x; if(var_a >= var_b) { x = var_a-var_b; result = x * var_c; } else { x = var_b - var_a; result = x * var_c; } } [出力コード] _f: MOV.L L14,R2 ; _var_a MOV.L L14+4,R4 ; _var_b MOV.W @R2,R5 MOV.W @R4,R2 MOV.L L14+8,R4 ; _var_c MOV R5,R6 SUB R2,R6 ; temp <- var_a-var_b MOV.W @R4,R7 EXTU.W R5,R5 EXTU.W R2,R2 CMP/GE R2,R5 BF/S L12 EXTU.W R7,R4 EXTU.W R6,R2 ; x <- (unsigned short)temp MOV.L L14+12,R5 ; _result MUL.L R2,R4 STS MACL,R2 RTS MOV.L R2,@R5 L12: EXTU.W R6,R6 MOV.L L14+12,R5 ; _result NEG R6,R2 ; x <- (long)(-temp) ; EXTU.W R2,R2を不当に削除 MUL.L R2,R4 STS MACL,R2 RTS MOV.L R2,@R5
発生条件:
次の条件を全て満たす時、発生することがあります。
void f() { unsigned short x; long temp = var_a ‐ var_b; if (var_a >= var_b) { result = (unsigned short)temp * var_c; /* var_a-var_b をtemp に置換 */ } else { result = (unsigned short)(-temp) * var_c; /* var_b-var_a を-temp に置換 */ } }
現象:
unsigned char/short型ポインタ変数のポインタ先と0との加減算もしくは1との乗算を行なう式を記述した場合、不当に変数のロード後のゼロ拡張命令を削除する場合があります。
[例] unsigned char *p; int a; void func(){ a = 0; a += *p; } [出力コード] _func: MOV.L L11,R5 ; _a MOV #0,R2 ; H'00000000 MOV.L R2,@R5 MOV.L L11+4,R2 ; _p MOV.L @R2,R6 MOV.B @R6,R2 ; ロード時に符号拡張 RTS MOV.L R2,@R5 ; ゼロ拡張せずに4byte 領域にストア
発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
関数マクロ呼び出しを複数行にわたって記述し、その複数行の間に'//'コメントを行の1 カラム目から記述した場合に、 6001 インターナルエラーになります。
[例] #define MACRO(a, b) a, b void func() { MACRO(1,0 // <- 1 カラム目から'//'コメント ); }
発生条件:
次の条件を全て満たす時、発生します。
現象:
C++言語の限定付名称を#pragmaに指定した場合に、4099インターナルエラーになる場合があります。ただし、コンパイル環境(ホストコンピュータのオペレーティングシステム)によって再現しないことがあります。
[例] class cPRINT { public: static void IntPrint(); }; #pragma interrupt(cPRINT::IntPrint) /* 限定を含む名称の長さが4 の倍数 */ void cPRINT::IntPrint(){}
発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
align16オプション指定時に、関数の最後が条件式で、関数呼び出しで終わっている節が複数あり、当該関数の後に別関数が続いている場合、分岐先不正になるかもしくはアセンブラ、最適化リンケージエディタでエラーになる場合があります。
[例] #include <stdio.h> void g( int a, int b, char *c); void func(int x) { switch (x){ case 0: g(0, 0, NULL); /* 条件式の最後が関数呼び出し */ break; default: g(0, 1, NULL); /* 条件式の最後が関数呼び出し */ break; } } main() { /* 別関数が続く */ func(0); }
発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
cpu=sh1オプション以外指定時に比較を行った場合、DT命令を不正に生成、またはADD 命令を不正に移動する場合があります。
[例1] struct tbl { char bit:1; }S,*Sp=&S; char a,b; func(){ int t; t = S.bit == 0; a = t << 1; if (t != 0 ) b++; } [出力コード] _func: MOV.L L14,R6 ; _S MOV.B @R6,R0 TST #128,R0 MOVT R6 ; (A)へ命令が不当に移動 TST R0,R0 ; -> TST R2,R2 MOVT R2 MOV.L L14+4,R5 ; _a SHLL R2 ADD # -1,R6 ; (A) 不当に移動 MOV.B R2,@R5 EXTS.B R6,R2 ; (A) 不当に移動 TST R2,R2 BF L12 MOV.L L14+8,R6 ; _b MOV.B @R6,R2 ADD #1,R2 RTS MOV.B R2,@R6 : [例2] char b; func2(int c, char d) { c = d - 1; b = c << 1; if(c != 0) { b++; } } [出力コード] _func: MOV.L L14+2,R6 ; _b EXTS.B R5,R2 SHLL R4 ; d-1 ではなく引数のc をシフトしている DT R2 ; c=d-1;およびc!=0 の判定を行っている BT/S L12 MOV.B R4,@R6 ADD #1,R4 RTS MOV.B R4,@R6 L12: RTS NOP
発生条件:
次の条件(a)、(b)を満たし、かつ(c)または(d)を満たす時、発生することがあります。
現象:
1バイト、または2バイトデータを複合代入で左シフトした結果を参照した場合に、不当に符号拡張またはゼロ拡張命令を削除する場合があります。
[例] short n; void func(short s){ sub(s <<= n); } [出力コード] _func: STS.L PR,@-R15 MOV.L L11,R6 ; _n MOV.W @R6,R1 MOV.L L11+4,R6 ; __sftl JSR @R6 EXTS.W R4,R0 MOV.L L11+8,R2 ; _sub MOV R0,R4 ; 演算結果が符号拡張されない JMP @R2 LDS.L @R15+,PR
発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
unsignedの型の変数や式どうしの減算結果を、signedの型にキャストして比較する場合に、不正に符号なし比較命令で比較を行なう場合があります。
[例] int test(unsigned int a, unsigned int b) { if ((int)(a - b) < 0) { return 1; } else { return 0; } } [出力コード] _test: CMP/HS R5,R4 ; (unsigned int)a < (unsigned int)bで比較 MOVT R0 RTS XOR #1,R0
発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
#pragma entryもしくは#pragma noregsaveを指定した場合、最適化リンケージエディタのレジスタ退避・回復最適化によりレジスタ退避・回復命令が不当に削除される場合があります。
発生条件:
次の条件を全て満たす時、発生することがあります。
現象:
符号付きビットフィールドの定数値比較('=='または'!=')において、定数値がビットフィールドの範囲を越えている場合に、比較結果が不正となる場合があります。
[例] struct tbl { unsigned int ib1:1; int ib8:8; } bf0 = {0,-2}; #include <stdio.h> main() { if (bf0.ib8 != 254) { /* 254(0xFE)を-2と判断してしまう */ printf("OK\n"); } }
発生条件:
次の条件(a)、(b)を満たし、かつ(c)、(d)、(e)のいずれかを満たした時、発生することがあります。
現象:
ループ内で符号なし変数を複数回参照した時、必要なゼロ拡張命令が削除される場合がある。
[例] extern unsigned char X; int sub(int a, int b, int n) { int i, sum=0; for (i = 0; i < n; i++) { if (X == (unsigned char)0xff) { // Xの参照 sum += a; } if (X == (unsigned char)0xf0) { // Xの参照 sum += b; } X = X + 1; // Xの定義 } return (sum); } [出力コード] _sub: MOV.L R12,@-R15 MOV.L R13,@-R15 MOV.L R14,@-R15 MOV R5,R13 MOV #0,R5 MOV.L L19,R1 ; _X MOV R6,R7 MOV R4,R12 MOV R5,R6 MOV #-1,R4 MOV.B @R1,R2 ; <- EXTU.B R2,R2が削除 MOV #-16,R14 EXTU.B R4,R4 BRA L11 EXTU.B R14,R14 L12: CMP/EQ R4,R2 ; 比較結果が正しくない場合あり(X>127の時) BF L14 ADD R12,R5 L14: CMP/EQ R14,R2 ; 比較結果が正しくない場合あり(X>127の時) BF L16 ADD R13,R5 L16: ADD #1,R2 EXTU.B R2,R2 ADD #1,R6 L11: CMP/GE R7,R6 BF L12 MOV.B R2,@R1 MOV R5,R0 MOV.L @R15+,R14 MOV.L @R15+,R13 RTS MOV.L @R15+,R12
発生条件:
次の(a)から(d)の条件、もしくは(e)から(h)の条件を全て満たす時、発生する可能性がある。
現象:
同じ値の浮動小数点定数を複数回使用した場合、不当に浮動小数点定数ロード式を削除する場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
配列アクセスa[c-exp]において、cが定数、expの型がunsigned char/unsigned shortのとき、配列を正しくアクセスできない場合がある。
[例] unsigned char dd[2]; void func(unsigned char a, unsigned char b) { dd[15-a] = b; } [出力コード] _func: MOV.L L11,R2 ; _dd NEG R4,R6 ; R6 <- -a EXTU.B R6,R0 ; -aをゼロ拡張 ADD #15,R2 RTS MOV.B R5,@(R0,R2) ; 異なるアドレスにアクセス
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
memmoveライブラリ関数でメモリ領域を上位アドレスのメモリ領域に移動すると、指定した文字数以上の移動を行ってしまう。
発生条件:
次の条件を全て満たす時、発生する。
現象:
関数の最後の処理が条件文で、条件がネストしており、かつ最後の条件節が関数呼び出し+return文、その前の条件節が関数呼び出しで終わっている場合、関数出口への無条件分岐が不当に削除される場合がある。
[例] void sub(int parm) { if (parm == 0) { ; } else if (parm == 1) { ; } else if (parm == 2) { ; } else if (parm == 3) { ; } else if (parm == 4) { ; } else if (parm == 5) { func1(); /* <A> */ } else { func2(); /* <B> */ return; /* <B> */ } return; } [出力コード] _sub: STS.L PR,@-R15 TST R4,R4 BT L11 MOV R4,R0 CMP/EQ #1,R0 BT L11 CMP/EQ #2,R0 BT L11 CMP/EQ #3,R0 BT L11 CMP/EQ #4,R0 BT L11 CMP/EQ #5,R0 BF L18 MOV.L L20+2,R2 ; _func1 JSR @R2 NOP L11: ; L19への分岐命令を削除 L18: MOV.L L20+6,R2 ; _func2 JMP @R2 ; 常に関数呼び出しされる LDS.L @R15+,PR L19: LDS.L @R15+,PR RTS NOP
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
unsigned型の変数をfloat型に明示的にキャストした時、キャストが不当に削除される場合がある。
[例] unsigned short us1; volatile unsigned short us0; volatile float f0; float *p; void func() { f0 = *p = ((float)us0, (float)us1); } [出力コード] _func: MOV.L L29+50,R2 ; _us0 MOV.L L29+54,R5 ; _p MOV.W @R2,R6 MOV.L L29+58,R6 ; _us1 MOV.W @R6,R2 EXTU.W R2,R6 MOV.L @R5,R2 MOV.L R6,@R2 ; floatに変換しないで*pにストア MOV.L @R5,R2 MOV.L @R2,R6 MOV.L L29+10,R2 ; _f0 RTS MOV.L R6,@R2 ; floatに変換しないでf0にストア
発生条件:
次のいずれかの条件を満たす時、発生する可能性がある。
現象:
SH-4でld_exp()またはst_ext()組み込み関数使用時にパラメータにローカル配列を指定した場合、不正にスタックポインタを移動するコードを出力する場合がある。
[例] #include <machine.h> void main() { float table[4][4], data1[4][4], data2[4][4]; : ld_ext(table); mtrx4mul(data1,data2); : } [出力コード] : FRCHG FMOV.S @R15+,FR0 ; R15を更新、この間で例外が発生した場合 上位のスタック領域が破壊 FMOV.S @R15+,FR1 ; | FMOV.S @R15+,FR2 ; | FMOV.S @R15+,FR3 ; | FMOV.S @R15+,FR4 ; | FMOV.S @R15+,FR5 ; | FMOV.S @R15+,FR6 ; | FMOV.S @R15+,FR7 ; | FMOV.S @R15+,FR8 ; | FMOV.S @R15+,FR9 ; | FMOV.S @R15+,FR10 ; | FMOV.S @R15+,FR11 ; | FMOV.S @R15+,FR12 ; | FMOV.S @R15+,FR13 ; | FMOV.S @R15+,FR14 ; | FMOV.S @R15+,FR15 ; | FRCHG ; | ADD #-64,R15 ; V :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
"シンボルアドレス+オフセット値"の初期値をもつ変数が多く存在する場合、内部エラー(4098)もしくはオブジェクト不正になる場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
[例] extern char g; #define DATA1A (&g+2147483647) #define DATA10A DATA1A, DATA1A, DATA1A, DATA1A, DATA1A,\ DATA1A, DATA1A, DATA1A, DATA1A, DATA1A #define DATA100A DATA10A, DATA10A, DATA10A, DATA10A, DATA10A,\ DATA10A, DATA10A, DATA10A, DATA10A, DATA10A /* 以下は(変数の数+offsetの合計桁数)=(3001+10*3001)=33011>33000となる */ char *a1[1000] = { DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A }; char *a2[1000] = { DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A }; char *a3[1000] = { DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A, DATA100A }; char *a = DATA1A;
現象:
ループ内にsigned型の変数iからunsigned型の変数vの減算i=i-vがあるとき、不当にゼロ拡張を行なう。
[例] int i = 319; unsigned char v = 97; main() { int f; for(f=0; f<5; f++){ i = i - v; /* -vの結果がゼロ拡張されて演算される。*/ } }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
char/short 型への型変換を行なった直後に浮動小数点型への型変換を行なうと、char/shortへの変換が行なわれない。
[例] unsigned short US = 256; int I; float F; main(){ char c; c = US; /* short型変数をchar型変数に型変換 */ I = 3 & c; /* char 型変数がレジスタに割り付く */ F = c; /* char 型から float 型への型変換 */ } [出力コード] _main: MOV.L _US,R6 MOV.L _I,R5 MOV.W @R6,R0 /* 256 -> R0 char型への型変換EXTUが出力されない */ LDS R0,FPUL /* 256のままfloatに変換している */ :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
cpu=sh4を指定してコンパイルした場合にFPSCRの設定コードをこえて不当にFPU命令をループ外に移動する。
[例] double dd; struct tag { short aa; long bb; char cc:5; } str; main() { int i; str.bb = 10; str.aa = 10; for(i=5; i>=0; i--){ str.cc = str.aa++; dd = str.bb; } } [出力コード] _main: MOV.L R14,@-R15 MOV #10,R5 ; H'0000000A MOV.L L13+2,R2 ; _dd LDS R5,FPUL MOV.L L13+6,R7 ; _str FLOAT FPUL,DR8 ; LDS R2 FPSCRをまたいでループ外に移動 ADD #8,R2 MOV #8,R1 ; H'00000008 : L11: MOV.B @(8,R7),R0 MOV R0,R6 : DT R4 OR R1,R2 LDS R2,FPSCR ; FLOAT FPUL,DR8 移動前の位置 ADD #1,R5 :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
最内側ループで割付けられたレジスタの内容が、そのループ内で破壊される。
[例] 複数の変数に対して同じレジスタを割り付けてしまいレジスタ内容が破壊されている。 for(i1 = 0; i1 < max1 ; i1++) { a = b; for(i2 = 0; i2 < max2 ; i2++) { /* (イ) */ c = x + b; /* (ロ) */ } /* (ハ) */ ans = a + c; } [出力コード] MOV.L @(R0,R15),R5 ;a にR5が割り付いている : MOV.L R5,@(R0,R15) ;aの退避 : ;ループ入口(イ) MOV.L @(R0,R15),R5 ;c にR5を割り付けた : L1: : ;ループ本体(ロ)(a の参照無し) MOV Rn,R5 ; c = x + b の結果をR5に格納 : BF L1 : ;ループ出口(ハ) MOV.L @(R0,R15),R5 ;cを退避せずにR5を上書き : MOV.L R5,Rn ;破壊されたc の値をロードしている
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
double/float切り替えコードが2つ出力されるとき、2回目のFPSCRロードが不正に削除される。
[例] double d0; float f0, f1, f2; main { int i; for(i = 0; i < 100; i++){ d0++; f1 = f1 + f0; } } [出力コード] _main: ; function: main MOV.L L13+2,R1 ; _d0 MOVA L13+6,R0 : L11: STS FPSCR,R2 DT R6 OR R5,R2 LDS R2,FPSCR FADD DR4,DR6 ; <--この後にSTS FPSCR,R2が必要 AND R4,R2 LDS R2,FPSCR BF/S L11 FADD FR9,FR8 ADD #8,R1 :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
戻り値を参照しない実行時ルーチンの引数に対して必要な符号拡張が行われない。
[例] 実行時ルーチン(__itod_a)への引数(unsigned long int) R0 に cを符号拡張した値を渡していない。 double D; int I; unsigned short US = 256; func2(){ char c; c = US; I = 3 & c; D = c; } [出力コード] _func2: STS.L PR,@-R15 ADD #-12,R15 MOV.L L20,R6 ; _US MOV.L L20+4,R5 ; _I MOV.W @R6,R2 MOV.L L20+16,R6 ; _D MOV R2,R0 AND #3,R0 MOV.L R6,@R15 MOV.L L20+20,R6 ; __itod_a MOV.L R0,@R5 ; <--この後に EXTS.B R2,R2が必要 JSR @R6 MOV R2,R0
発生条件:
次の条件を満たす時、発生する可能性がある。
現象:
ポインタを介して2次元以上の構造体配列のある要素のメンバを参照したとき、そのメンバへ設定/参照が正しく行なわれない。
[例] typedef struct { int aaa; } ST; void main() { ((ST (*)[2])0x10000)[0]->aaa = 100; /* 0x10000[0][0].aaaへの設定が正しく行われない */ }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
latin1を指定してコンパイルした際に、一部正常なlatin1コードに対して不当にエラーメッセージを出力する。
現象:
割り込み関数のスタックサイズ情報(リスティングファイル/アセンブリソースのスタックフレームサイズ)に、CPUが暗黙的に使用するPCとSRの退避分が含まれていない。
発生条件:
次の条件を全て満たす時、発生する可能性がある。