現象:
レジスタ渡しパラメタのアドレスを参照すると、スタック上のデータを不正に上書きする場合がある。
[例] extern void er(); extern char f2(char *a); void f(char a) { char c; a++; // レジスタ渡しパラメタに代入 do { c=f2(&a); // レジスタ渡しパラメタのアドレスを参照 if(c) er(); else return; } while(c); } [出力コード] _f: MOV.L R13,@-R15 MOV.L R14,@-R15 STS.L PR,@-R15 ADD #-4,R15 MOV R4,R0 ADD #1,R0 MOV.B R0,@(3,R15) ; ※ MOV.L R4,@R15 ; ※で設定したaの値を上書き MOV.L L14+2,R13 ; _f2 :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
#pragma global_register指定したレジスタの代入を不正に削除する場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
[例] #pragma global_register (a=R14) : a += b; // もしくは a=a+b;
現象:
32bitビットフィールドを0と比較した場合、比較前に不正な0とのANDが生成され、判定結果が常に真(または偽)となる場合がある。
[例] struct ST { unsigned int b: 32; }; void f(struct ST *x) { if (x->b) { : } } [出力コード] : MOV.L @R4,R0 AND #0,R0 ; 0とANDをとる TST R0,R0 ; 必ず真となる BF L12 ; L12への分岐は起きない :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
pic=1を指定してコンパイルした場合、組み込み関数trapa_svcを使用している関数のアドレスロード時に、不当にスタック移動命令を出力する場合がある。
[例] #include <machine.h> extern char *b(void (*yyy)(char)); void y(char c) { trapa_svc(160, 10, c); } char *a(void) { return b(y); } [出力コード] _a: MOV.L L14,R4 ; _y-L12 MOVA L12,R0 ADD R0,R4 L12: MOV.L @R15+,R0 ; 不要なスタック移動命令 MOV.L L14+4,R2 ; _b-L13 MOVA L13,R0 ADD R0,R2 L13: JMP @R2 MOV.L @R15+,R0 ; 不要なスタック移動命令
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
最適化により、R0-R7へのコピー命令もしくは拡張命令が関数呼び出しを超えて不正に移動し、CMP/EQ(TST)の結果が不正となる場合がある。
[例] : MOV.L @R4,R2 MOV R5,R14 MOV #1,R5 ; H'00000001 ADD #24,R2 MOV.L @R2,R6 EXTU.W R14,R1 ; R1の定義がJSRを越えて移動 MOV.L @(8,R2),R7 JSR @R7 ; 呼び出し先でR1を破壊する場合あり ADD R6,R4 MOV #4,R2 ; H'00000004 CMP/EQ R2,R1 ; 破壊されたR1の値を使って比較 EXTU.W R0,R0 BF L16 :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
[最適化前] MOV R0, Rn ; またはEXTU R0,Rn : MOV Rx, R0 ; またはEXTU Rx,R0 TST #imm, R0 ; またはCMP/EQ #imm,R0 MOV Rn, R0 ; または EXTU Rn,R0 [最適化後] MOV Rx, Rm ; またはEXTU Rx,Rm MOV #imm, Ry TST Ry, Rm ; またはCMP/EQ Ry,Rm
現象:
スタック渡しのパラメタがある時、R0を不正に書き換える場合がある。
[例] short func1(short a0, int *a1, int a2, short a3, short a4, short a5, short a6, int a7, int a8, int a9); void func0(short a0, int *a1, int a2, short a3, short a4, short a5, short a6) { : r1=func1(0,a1,0,0,0,0,0,0,0,0); if((r1>0)&&(r1!=1)) { func1(a0,a1,0,a3,a4,a5,a6,0,0,0); } : } [出力コード] : MOV.L R0,@(32,R15) ; R0を@(32,R15)に退避 MOV R8,R5 MOV #66,R0 ; R0を破壊 MOV.W @(R0,R15),R3 MOV R9,R6 MOV #70,R0 ; R0を破壊 MOV.W @(R0,R15),R1 MOV R0,R4 ; MOV.L @(32,R15),R4をMOV R0,R4に置換えコード不正 MOV.L R3,@(4,R15) MOV.L R1,@(8,R15) MOV.L R9,@(12,R15) MOV.L R9,@(16,R15) BSR _func1 MOV.L R9,@(20,R15) :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
無条件分岐を含むプログラムにおいて、分岐がBRA命令で、かつ飛び先までの距離が4094バイトの時、飛び先が不正になるコードを生成する場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
次のソースをspeedオプションでコンパイル時、不当にPRレジスタの退避・回復命令を削除し、実行時に無限ループする場合がある。
[例] int x; extern void f1(); extern void f2(); void f() { if (x == 2){ f1(); // then節が関数呼び出しで終わっている } f2(); // 関数の最後の処理が関数呼び出し return; } [出力コード] _f: MOV.L L14,R6 ; _x MOV.L @R6,R0 CMP/EQ #2,R0 BT L11 L12: MOV.L L14+4,R2 ; _f2 JMP @R2 ; 関数の最後が関数呼び出しのため、JMP命令に NOP ; 変換し、RTS を削除 L11: MOV.L L14+8,R2 ; _f1 JSR @R2 ; ここに関数呼び出し命令があるにも関わらず NOP ; PRレジスタの退避回復が行われていない BRA L12 NOP
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
以下のケースにおいて、不当に条件分岐を行なう場合がある。
[例] #include <machine.h> extern void f(); int a; void func() { int b; b = (a == 0); // 比較結果を変数に格納(A) f(); // 関数呼び出しまたは組み込み関数set_cr() if(b) { //(a)の変数を0/1比較 a=1; } } [出力コード] _func: STS.L PR,@-R15 MOV.L L13,R6 ; _a MOV.L @R6,R2 TST R2,R2 ; 比較結果をTビットに格納 MOV.L L13+4,R2 ; _f JSR @R2 ; 関数呼び出し先でTビットが NOP ; 破壊される可能性あり BF L12 ; Tビットを参照し分岐 MOV.L L13,R6 ; _a MOV #1,R2 MOV.L R2,@R6 L12: LDS.L @R15+,PR RTS NOP
発生条件:
次の(a)〜(c)または(d)〜(e)の条件を全て満たす時、発生する可能性がある。
現象:
次のソースをoptimize=1でコンパイル時、定数値を不当に共通化し、参照時の値が実際と異なる場合がある。
[例] #define a (*(volatile unsigned short *)0x400) #define b (*(volatile unsigned short *)0x4000) #define c (*(volatile unsigned short *)0x402) int d; void func() { a = 0x8000; /* (A) */ b = 0x8000; /* (A') */ d = c + 0x8000; /* (B) */ } [出力コード] _func: MOV.W L15,R6 ; H'8000 R6に0xFFFF8000を設定 MOV #4,R5 MOV #64,R2 SHLL8 R5 SHLL8 R2 MOV.W R6,@R5 ; (A) aに0x8000を設定 MOV.W R6,@R2 ; (A') bに0x8000を設定 MOV.W @(2,R5),R0 EXTU.W R0,R2 ADD R6,R2 ; R2にc+0xFFFF8000の結果を設定 MOV R2,R6 MOV.L L15+4,R2 ; _d RTS MOV.L R6,@R2 ;(B) dにc+0xFFFF8000の結果を格納しNG
発生条件:
次の条件を全て満たす時、発生する。
現象:
align16オプションを指定してコンパイルした場合、リテラルプールの参照が届かなくなる場合がある。
[例] : MOV.L L154+2,R2 ; L158 リテラル(A)を参照(1) MOV.L R2,@R15 MOV.L L154+6,R2 ; _printf リテラル(B)を参照(2) JSR @R2 NOP : .ALIGN 16 L86: ADD #1,R2 BRA L153 ; 無条件分岐を生成しリテラルを出力 MOV.L R2,@R4 L154: .RES.W 1 .DATA.L L158 ;(A) (1)からdispが届かない位置にリテラル出力 .DATA.L _printf ;(B) (2)からdispが届かない位置にリテラル出力 .ALIGN 16 L153: :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
optimize=1を指定してコンパイルした場合、不当に遅延スロットに命令を移動し、レジスタを破壊する場合がある。
[移動前] : SHLL R2 MOV R2,R0 MOVA L88,R0 BRA L144 NOP : [移動後] SHLL R2 ; 遅延スロットに移動 MOVA L88,R0 ; R0に値を設定 BRA L144 MOV R2,R0 ; MOVAで設定したR0を破壊 :
発生条件:
同一レジスタに値を設定するコードが連続する時、発生する可能性がある。
現象:
optimize=1を指定してコンパイルし、かつ1バイト構造体メンバの論理演算をGBR相対で行なうコードを生成した場合、そのoffset値が不正になる場合がある。
[例] struct { int a; unsigned char b; } ST; char c; void f() { ST.b |= 1; c &= 1; } [出力コード] _f: STC GBR,@-R15 MOV #0,R0 ; H'00000000 LDC R0,GBR MOV.L L11+2,R0 ; H'00000008+_ST <- 実際は(ST+4) OR.B #1,@(R0,GBR) MOV.L L11+6,R0 ; _c AND.B #1,@(R0,GBR) RTS LDC @R15+,GBR
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
optimize=1を指定してコンパイルした場合、組み込み関数swapb、swapw、end_cnvlの結果代入先にポインタを指定すると、不当にゼロ拡張を行う場合がある。
[例] #include <machine.h> unsigned short *a,*b; void func() { *b=swapb(*a); } [出力コード] _func: MOV.L L13+2,R2 ; _a MOV.L L13+6,R5 ; _b MOV.L @R2,R6 MOV.W @R6,R2 SWAP.B R2,R6 MOV.L @R5,R2 EXTU.B R6,R6 ; SWAP結果を不正にゼロ拡張 RTS MOV.W R6,@R2
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
無名ビットフィールhを含む構造体に初期値を設定した場合、その初期値が不正になる場合がある。
[例] struct st { short a:4; short b; short :12; // 無名ビットフィールド short c:4; } ST={1,1,3}; [出力コード] _ST: .DATA.W H'1000 .DATA.W H'0001 .DATAB.B 1,0 ; 正しくは .DATA.W H'0300 ; .DATA.W H'0003
発生条件:
次の条件を全て満たす時、発生する可能性がある。
struct A{ : ビットフィールド : ビットフィールドでないメンバ 無名ビットフィールド //(A) ビットフィールド //(B) : };
現象:
speedオプションまたはloopオプション指定時、ループ展開最適化でループ判定式を不当に置きかえる場合がある。
[例] int a[100]; void main(int n) { int i; for (i=0; i<n; i++) { a[i] = 0; } } [出力コード] _main: MOV R4,R7 ADD #-1,R4 ; R4が0x80000000の場合、アンダフローとなり ; R4は0x7FFFFFFFとなる MOV R4,R6 CMP/PL R4 ; 比較結果が実際の結果と逆になる MOV #0,R4 BF L12 ADD #-1,R6 :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
上限値が変数の場合、変数にa.またはb.を満たす値が設定されている場合に動作不正になる。
現象:
関数の引数に構造体/共用体または配列を使用した場合、そのメンバや配列要素を参照する時に、不正なアドレスを参照する場合がある。
[例] typedef struct{ int A[10]; double B; char F[20]; } ST; extern ST f(ST a,ST b); ST S; extern int X; void func(ST a,ST b) { ST t; if (a.B!=f(S,t).B){ X++; } if (a.B!=b.B){ X++; } } [出力コード] : L12: MOV R15,R2 MOV.W L15+2,R0 ; H'014C ADD R0,R2 MOV R15,R0 MOV.W L15+4,R0 ; H'0190 R0を不正に破壊 ADD R0,R0 MOV.L @R2,R4 MOV.L @(4,R2),R7 MOV R0,R2 MOV.L @R2,R6 ; b.Bでない場所をアクセス :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
speedオプションを指定してコンパイルした場合、JMP命令を不当に削除する場合がある。
[例] void f(){ int i,j=0; for (i=0; i<10; i++) if (j%2) j++; sub(); } void sub() { : } [出力コード] _f: : L20: ADD #-1,R5 TST R5,R5 BF L11 MOV.L L23,R2 ; _sub 以下3命令が削除される JMP @R2 ; | NOP ; V L18: MOV R6,R0 AND #1,R0 BRA L16 MOV R0,R2 L13: MOV R6,R0 AND #1,R0 BRA L14 MOV R0,R2 _sub: :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
次のCソースをoptimize=1でコンパイル時、ループ判定式を不当に置きかえる場合がある。
[例] void f1() { int i; for (i=-1; i<INT_MAX; i++) { a[i] = 0; } } [出力コード] _f1: MOV.L L13,R2 ; _a MOV #-4,R6 ; H'FFFFFFFC MOV R6,R5 MOV #0,R4 ; H'00000000 ADD #-4,R2 L11: ADD #4,R6 MOV.L R4,@R2 CMP/GE R5,R6 ; H'FFFFFFFCと比較 ADD #4,R2 BF L11 RTS NOP
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
if文の削除最適化で副作用のある条件式が削除される場合がある。
[例] extern int sub(); main() { int i=0; if(sub()) { /* if文内の関数sub()の呼び出しが不正に削除される */ i=10; /* ローカル変数iはこの後どこでも使用されないので */ } /* 最適化によりi=10が削除される */ }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
スタックに対するロード・ストアが不正になる場合がある。
[例] : MOV R15,R2 ADD #72,R2 MOV #104,R0 ; H'00000068 MOV.L R2,@(R0,R15) <- (SP+72)にデータを保存 MOV R15,R3 ADD #92,R3 <- 正しくは#72 MOV.L @R3,R6 <- (SP+92)からデータ取り出し NG MOV.L L37+60,R4 ; L52 BSR _func MOV #52,R5 ; H'00000034 :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
#pragma interrupt関数から#pragma inline_asm指定関数を呼び出し時、#pragma inline_asm関数内で使用したレジスタが破壊されることがある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
macsave=1オプション指定時、#pragma regsave指定関数でMACレジスタが退避・回復されない。
発生条件:
次の条件を全て満たす時、発生する。
現象:
二重ループのある式でspeedオプションまたはloopオプションを指定すると、コード不正になる場合がある。
[例] : for(...) for(...) x = x + i; /* xの値が不正になることがある */ :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
不要なロード・ストア命令削除または複数ロード命令削除で不正にEXTS命令を削除してしまう場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
switch文がテーブル方式展開される場合、遅延スロットにケーステーブルのリテラルデータが入り、コード不正になる場合がある。
[例] SHLL R6 MOVA L204,R0 MOV.W @(R0,R6),R0 BRAF R0 NOP L203: .RES.W 1 .DATA.L _fl .DATA.L _f2 .DATA.L _f3 .DATA.L _f4 .DATA.L _f5 .DATA.L _f6 L204: .DATA.W L143-L203 .DATA.W L143-L203 BRA L180 .DATA.W L143-L203 ←遅延スロットに入る
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
定数演算でコード不正になる場合がある。
[例] void f() { sl = 0x80000001L; : if (*scp16==(char)(0x80000001L)) : /* 0x80000001を1byteに型変換した結果(1)と比較 */ /* すべきところ、0x80000001と比較 */ }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
ポインタの指示先への値の設定が正しく行われない場合がある。
[例] int *gp; void g(int *p) { gp = p; } int f(int *q) { static int i, *p = &i; g(p); /* gpがiを指すように設定される */ : i = 1; *gp = 2; /* *gpとiが同一である可能性があることが認識できていない */ : return i; /* i = 1が定数伝播され、2ではなく1が返される */ }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
#pragma interrupt指定関数でFPSCRが退避・回復されない。
発生条件:
次の条件を全て満たす時、発生する。
現象:
以下の組み込み関数を跨いで命令が移動することがある。
set_cr, get_cr, set_imask, get_imask, set_vbr, get_vbr, trapa, trapa_svc, prefetch
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
乗算結果を1/2byteに代入時、不正に拡張命令が削除される場合がある。
[例] unsigned short eus=32768,eus2=32769; void func () { unsigned short aus; aus= (eus--) * (eus2--); /* 乗算結果のゼロ拡張が不正に削除 */ if (aus!=(unsigned short)((1+eus)*(1+eus2))){ : /* (1+eus)*(1+eus2)の結果はゼロ拡張される */ }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
volatileへのポインタに型変換を指定時、ループ内の式のvolatile指定が無効になる場合がある。
[例] #define ADDRESS1 0xf0000000 #define ADDRESS2 0xf0000004 #define BIT0 0x0001 void shc_test(void) { unsigned short dataW,read_val; read_val = *((unsigned short*)ADDRESS1); while(1) { /* volatileが無効になりループ外に移動 */ dataW = *((volatile unsigned short*)ADDRESS2); if(dataW & BIT0) { /* volatileが無効になりループ外に移動 */ *((volatile unsigned short*)ADDRESS2) &= ~BIT0; break; } } }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
外部変数の複合論理演算指定時に、コード不正になる場合がある。
[例] unsigned char guc1=255; void func001() { if (guc1 & 254){ /* guc1をロード(A) */ guc1 &= 253; /* AND.B #253,@(R0,GBR) メモリ上のguc1を書き換え */ } if (guc1==253) ok(1); /* guc1を再ロードせず、(A)をそのまま使用 */ else ng(1); }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
1/2byte変数を#pragma global_register指定すると、不正にEXTS/EXTU命令が削除される場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
構造体・共用体に構造体・共用体配列メンバがある場合にオブジェクト不正になる場合がある。
[例] void func() { struct tag { union { short u11; char u12[2]; } u1[2]; } st= {{{0x1234},{0x5678}}}; char ans1; ans1=st.u1[1].u12[1]; /* st.u1[1].u12[1]設定前にans1をコピー(A) */ printf("%x\n",ans1); /*(A)のans1をそのまま使用 */ if(ans1 == 0x78) /*(A)のans1をそのまま使用 */ :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
goptimize指定時に、レジスタ退避・回復コードが遅延スロットに移動した場合、optlnkで不正に退避・回復コードを削除する場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
組込み関数nopを引用した場合、不当に遅延スロットにNOP命令を移動し指定位置に設定できない。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
定数値をcharまたはshort型に明示的型変換指定をした場合、コード不正になる場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
関数パラメタにvolatile変数に対する後置++/--式を記述した時、呼び出し関数内で当該変数が後置++/--前の値になる場合がある。
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
rtnextオプション指定時、1/2byteのリターン値が不正になる場合がある。
[例] int a; unsigned char func(){ return a; /* aの上位3byteは不定値が返る */ }
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
endian=little指定時、構造体メンバに無名ビットフィールドがあるとデータ配置が不正となる場合がある。
発生条件:
次の(a)-(d)もしくは(e)-(h)の条件を全て満たす時、発生する可能性がある。
現象:
volatile宣言された変数について、次のような式を記述した場合、変数の参照を保証するように変更した。
a &= 0;
現象:
ローカル配列、構造体・共用体(スタックに領域を確保した時)のデバッグ情報が出力されなかった。
現象:
次の条件でインターナルエラーが発生する場合がある。
現象:
関数内に結果が同じ整数型の部分式が存在する場合、その結果の下位2バイトまたは1バイトを不正に符号拡張/ゼロ拡張する場合がある。
[例] short sub(long); short a,b,c,d; void f() { if(d) { b = sub((long)a * (long)b * (long)c / 0x4000); /* ^^^^^^^^^^^^^^^^^ */ } else { b = sub((long)a * (long)b * / 0x80); /* ^^^^^^^^^^^^^^^^^ */ } }
発生条件:
次の条件を全て満たす時、発生する。
現象:
optimize=1 指定時、使用中のレジスタを不正に破壊する場合がある。
発生条件:
次の条件を全て満たす時、発生する。
現象:
同じ構造体の1ビットフィールドメンバへの定数代入文が連続し、かつ同じビットフィールドメンバへの代入文が複数存在する時、インターナルエラーもしくはオブジェクト不正になる場合がある。
[例] struct { unsigned char b1:1; unsigned char b2:1; } ST; /* インターナルエラー */ void f() { ST.b1=1; ST.b2=0; ST.b2=0; } /* オブジェクト不正 */ void g() { ST.b1=1; ST.b2=1; ST.b2=0; }
発生条件:
次の条件を全て満たす時、発生する。
現象:
割り込み関数内で、R0,R1,R3が使用されているにも関わらず退避・回復されない場合がある。
発生条件:
次の条件を全て満たす時、発生する。
現象:
optimize=1指定時、使用中のレジスタR0を不正に破壊してしまう場合がある。
[例] ret = func(a,b,c); func2(d,e,f,g,h,ret,i,j); : [出力コード] JSR @R2 MOV.L @(R0,R15),R8 MOV.B R0,@(28,GBR) ; <- func()の戻り値をretに格納 EXTU.B R14,R6 MOV.W L2448+8,R0 ; H'0087 ; <- R0を破壊 MOV.B @(R0,R15),R5 MOV R10,R4 MOV.W L2448+4,R0 ; H'0083 ; <- R0にH'0083を設定 MOV.B @(R0,R15),R7 STC GBR,R2 ADD #18,R2 MOV.L R9,@R15 MOV.L R2,@(8,R15) EXTU.B R5,R5 STC GBR,R2 ADD #56,R2 MOV.B R0,@(7,R15) ; <- R0(H'0083)をfunc2()の第6引数 EXTU.B R7,R7 ; として設定 BSR _func2 MOV.L R2,@(12,R15) :
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
switch文の条件式にネストした構造体のメンバ参照を記述した場合、メンバへのオフセットが不正となる場合がある。
[例] struct ST1 { int B0; int B1; int B2; int B3; }; struct ST { struct ST1 A0; struct ST1 A1; struct ST1 A2; struct ST1 A3; }; int x; test(struct ST *s) { switch ((&s->A1)->B2) { case 1: x=1; } } [出力コード] MOV.L @(8,R4),R0 ; <- @(24,R4)が正しい CMP/EQ #1,R0 BF L15 MOV.L L17+2,R6 ; _x MOV #1,R2 ; H'00000001 RTS MOV.L R2,@R6 L15: RTS NOP
発生条件:
次の条件を全て満たす時、発生する可能性がある。
現象:
構造体メンバが関数へのポインタで、その関数の型がプロトタイプ形式で宣言されている場合に、デバッグ情報が不正になる。
発生条件:
次の条件を全て満たす時、発生する。
現象:
次の場合、インターナルエラーが発生する。