Skip to main content

定数伝播

とともに CODESYS Static Analysis バージョン V5.0.0.0 では、コードの分析は定数伝播に基づいています。定数伝播の結果はさまざまなチェックに使用されます。たとえば、ポインタが 0 に等しくないか、配列インデックスが有効範囲外かどうかをチェックします。

この分析がどのように機能するのか、またその制限は何なのかを知るだけで、静的分析を効果的にサポートできます。

定数伝播

静的分析では、変数の使用状況に基づいて変数の値を決定しようとします。

1.
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 は。



ローカルで実行される定数伝播

値は機能ブロック内でローカルにのみ決定されます。入力がどのように渡されるかは関係ありません。関数呼び出しの結果も無関係です。

2.
FUNCTION Func : BOOL
//Declaration
VAR_INPUT
    bText : BOOL;
END_VAR
//Implementation
IF bTest THEN
    Func := OtherFunc(TRUE);
END_IF


パラメータであっても、 bTest に設定されています TRUE すべての呼び出しにおいて、これは定数の伝播には影響しません。たとえ OtherFunc(TRUE) 常に戻ってきます TRUE、これは定数伝播には影響しません。

初期値を持つのは一時変数のみです。

プログラムやファンクションブロック内の静的ローカル変数には、想定される初期値がありません。変数は最後の呼び出しからの値を保持しているため、原則として「任意」にすることができます。

関数内のローカル変数と一時変数には、呼び出しごとに初期値があります。定数伝播はこの初期値で計算されます。

3.
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

常に最初に書き込まれてから一時変数として読み取られる変数を宣言することをお勧めします。



定数の伝播により、数値データ型の値の範囲が決まります。

複雑さを軽減するために、変数ごとに上限と下限のある値の範囲が決定されます。

4.
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 値の範囲内です。



繰り返し発生する複雑な式は、同じ変数として認識されません。

複雑な式には値が割り当てられていない場合があります。このような式が複数回出現する場合は、補助変数を導入すると便利です。

5.
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 行目の配列へのアクセスが許可されます。



分岐

分岐の場合、個々の分岐は個別に計算されます。次に、個々の範囲の値範囲が結合されて、新しい値範囲が形成されます。

6.
//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]



条件

7.

条件により、コード ブロック内の変数の値の範囲を制限できます。いくつかの条件を組み合わせることができます。相互に排他的な条件により、値の範囲が空になる場合もあります。

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 も使用します。これは、これらの値が関連することが多いためです。

8.

手順を説明する最も簡単な方法は、次の例です。

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

定数の伝播では、ループについて次のことがわかります。

ix、 そして y ループの最初の実行の開始時には 0 です。条件 i <= 5 ループ内のコードに適用されます。条件 i > 5 ループ後のコードに適用されます。

ループ内の変数の値については、定数の伝播によって次の値が決定されます。

i

x

y

[0..5]

[0..MAXDINT]

[0..5]

詳細には、次の中間ステップが実行されます。

合格

i

x

y

1

0

[0..1]

0

i 0 で初期化されました。 y は常に i と同じ値を取得します。

2

[0..1]

[0..2]

[0..1]

6

[0..5]

[0..6]

[0..5]

まずは範囲 [0..6] 実際に計算されるのは i。ただし、知られているのは、 i < 5 が条件です。したがって、ループ内のコードの値はこの値に制限されます。

7

[0..5]

[0..7]

[0..5]

10

[0..5]

[0..10]

[0..5]

x どんどん増えていきます。から 10ただし、値は「切り上げ」られます。 MAXINT

11

[0..5]

[0..MAXDINT]

[0..5]

MAXDINT + 1 結果として MAXDINT

11日現在

11 回目のパス以降、ループ内の値は変更されません。伝播は終了します。

さらに、 i = 6 このループに続くコードに適用されます。範囲 [0..6] ループ内で決定され、これが条件と組み合わされます。 i > 5、その結果は正確に値 6 になります。