定数伝播
とともに CODESYS Static Analysis バージョン V5.0.0.0 では、コードの分析は定数伝播に基づいています。定数伝播の結果はさまざまなチェックに使用されます。たとえば、ポインタが 0 に等しくないか、配列インデックスが有効範囲外かどうかをチェックします。
この分析がどのように機能するのか、またその制限は何なのかを知るだけで、静的分析を効果的にサポートできます。
定数伝播
静的分析では、変数の使用状況に基づいて変数の値を決定しようとします。
PROGRAM PLC_PRG //Declaration VAR x: INT; bTest: BOOL; END_VAR
//Implementation x := 99; IF x < 100 THEN bTest := TRUE; END_IF
1 行目の実装では、定数の伝播によって値が記録されます。 99
変数の場合 x
この値をさらなる分析に使用します。分析により、次の式が認識されます。 IF
-ステートメント定数 TRUE
は。
ローカルで実行される定数伝播
値は機能ブロック内でローカルにのみ決定されます。入力がどのように渡されるかは関係ありません。関数呼び出しの結果も無関係です。
FUNCTION Func : BOOL //Declaration VAR_INPUT bText : BOOL; END_VAR
//Implementation IF bTest THEN Func := OtherFunc(TRUE); END_IF
パラメータであっても、 bTest
に設定されています TRUE
すべての呼び出しにおいて、これは定数の伝播には影響しません。たとえ OtherFunc(TRUE)
常に戻ってきます TRUE
、これは定数伝播には影響しません。
初期値を持つのは一時変数のみです。
プログラムやファンクションブロック内の静的ローカル変数には、想定される初期値がありません。変数は最後の呼び出しからの値を保持しているため、原則として「任意」にすることができます。
関数内のローカル変数と一時変数には、呼び出しごとに初期値があります。定数伝播はこの初期値で計算されます。
PROGRAM PLC_PRG //Declaration VAR x: INT := 6; bTest: BOOL; END_VAR VAR_TEMP y : INT := 8; END_VAR
bText := x < y;
変数 y
毎回実行される PLC_PRG
値は 8 です。変数 x
ただし、必ずしもそうではありません。したがって、定数伝播は次の場合にのみ使用されます。 y
値を仮定しますが、 x
。
常に最初に書き込まれてから一時変数として読み取られる変数を宣言することをお勧めします。
定数の伝播により、数値データ型の値の範囲が決まります。
複雑さを軽減するために、変数ごとに上限と下限のある値の範囲が決定されます。
PROGRAM PLC_PRG VAR x: INT := 6; bTest: BOOL; y : INT; END_VAR
//Implementation IF bTest THEN x := 1; ELSSE x := 100; END_IF IF x = 77 THEN y := 13; END_IF
ここでの値の範囲は [1..100]
変数に対して決定されます x
。その結果、7 行目で比較が行われます。 x = 77
は定数式として認識されません。 77
値の範囲内です。
繰り返し発生する複雑な式は、同じ変数として認識されません。
複雑な式には値が割り当てられていない場合があります。このような式が複数回出現する場合は、補助変数を導入すると便利です。
PROGRAM PLC_PRG VAR x: DINT; py : POINTER TO INT; y : INT; testArray : ARRAY [0..4] OF DINT; END_VAR
//Implementation IF py^ >= 0 AND py^<= 4 THEN x := testArray[py^]; END_IF y := py^; IF y <= 0 AND y <=4 THEN x := testArray[y]; END_IF
2 行目では、ポインタが指す領域はチェックされていますが、値へのポインタを介したアクセスの可能性に対してエラーが発行されます。最初に値がローカル変数にコピーされ、その範囲がチェックされると、定数の伝播によってその変数の値の範囲が決定され、7 行目の配列へのアクセスが許可されます。
分岐
分岐の場合、個々の分岐は個別に計算されます。次に、個々の範囲の値範囲が結合されて、新しい値範囲が形成されます。
//Implementation IF func(TRUE) THEN x := 1; ELSE x := 10; END_IF IF func(FALSE) THEN y := x; ELSE Y := 2*x; END_IF
6行目で、 x
範囲があります [1..10]
。 11行目以降、 y
値の範囲があります [1..20]
;これは 2 つの値の範囲を結合した結果です [1..10]
そして [2..20]
。
条件
条件により、コード ブロック内の変数の値の範囲を制限できます。いくつかの条件を組み合わせることができます。相互に排他的な条件により、値の範囲が空になる場合もあります。
IF y > 0 AND y < 10 THEN x := y; ELSE x:= 0; END_IF IF x < 0 THEN i := 99; END_IF
y には値の範囲があります [1..9]
2 行目。これにより、値の範囲が決まります。 [0..9]
のために x
6行目。条件と組み合わせる x < 0
、これにより、可能な値の空のセットが得られます。 x
8 行目。コードにアクセスできません。静的解析では、次のような状態がレポートされます。 x < 0
常に戻ってきます FALSE
この時点で。
ループ
定数の伝播では、ループ内の変数の値が変更されなくなるまでコードがループされます。ループは何度でも実行できると想定されています。これまでに決定された値は、以前の値と結合されます。ループ内で変更される変数の範囲は連続的に増加します。ここで、定数の伝播では範囲のすべての可能な値を取得するのではなく、コード内で発生する制限のみを使用し、値 0、1、2、3、および 10 も使用します。これは、これらの値が関連することが多いためです。
手順を説明する最も簡単な方法は、次の例です。
PROGRAM PLC_PRG VAR x: DINT; i : DINT; y : DINT; END_VAR
//Implementation x := 0; y := 0; FOR i := 0 TO 5 DO x := x + 1; y := i; END_FOR
定数の伝播では、ループについて次のことがわかります。
i
、 x
、 そして y
ループの最初の実行の開始時には 0 です。条件 i <= 5
ループ内のコードに適用されます。条件 i > 5
ループ後のコードに適用されます。
ループ内の変数の値については、定数の伝播によって次の値が決定されます。
|
|
| ||
---|---|---|---|---|
|
|
|
詳細には、次の中間ステップが実行されます。
合格 |
|
|
| |
---|---|---|---|---|
1 | 0 |
|
|
|
2 |
|
|
| |
6 |
|
|
| まずは範囲 |
7 |
|
|
| |
10 |
|
|
|
|
11 |
|
|
|
|
11日現在 | 11 回目のパス以降、ループ内の値は変更されません。伝播は終了します。 |
さらに、 i = 6
このループに続くコードに適用されます。範囲 [0..6]
ループ内で決定され、これが条件と組み合わされます。 i > 5
、その結果は正確に値 6 になります。