Constant Propagation
With the CODESYS Static Analysis version V5.0.0.0, the analysis of the code is based on constant propagation. The results of constant propagation are used for various checks. For example, it checks if pointers are not equal to 0, or if array indices are out of valid range.
You can effectively support static analysis just by knowing how this analysis works and what its limitations are.
Constant propagation
Static analysis attempts to determine the value of a variable based on its usage.
PROGRAM PLC_PRG //Declaration VAR x: INT; bTest: BOOL; END_VAR
//Implementation x := 99; IF x < 100 THEN bTest := TRUE; END_IF
In the implementation in line 1, the constant propagation records the value 99
for the variable x
to use this value for further analysis. The analysis then recognizes that the expression in the following IF
-Statement constant TRUE
is.
Locally performed constant propagation
A value is determined only locally in the function block. It is irrelevant how an input is passed. The results of function calls are also irrelevant.
FUNCTION Func : BOOL //Declaration VAR_INPUT bText : BOOL; END_VAR
//Implementation IF bTest THEN Func := OtherFunc(TRUE); END_IF
Even if the parameter bTest
is set to TRUE
on every call, this has no effect on the constant propagation. Even if OtherFunc(TRUE)
always returns TRUE
, this has no effect on constant propagation.
Only temporary variables have initial values.
Static local variables in programs and function blocks have no assumed initial value. The variables keep their values from the last call and can therefore be "anything" in principle.
Local variables in functions and temporary variables have an initial value on each call. The constant propagation calculates with this initial value.
PROGRAM PLC_PRG //Declaration VAR x: INT := 6; bTest: BOOL; END_VAR VAR_TEMP y : INT := 8; END_VAR
bText := x < y;
The variable y
is executed every time PLC_PRG
have the value 8. The variable x
, however, not necessarily. Therefore, constant propagation is only used for y
assume a value, but not for x
.
It is recommended to declare variables which are always written first and then read as temporary variables.
Constant propagation determines value ranges for numeric data types.
To reduce complexity, a range of values with upper and lower limits is determined for each variable.
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
Here the value range [1..100]
is determined for the variable x
. As a result, on line 7, the comparison x = 77
is not recognized as a constant expression because 77
is within the range of values.
Recurring complex expressions are not recognized as the same variable.
Complex expressions may not have a value assigned. If such expressions occur multiple times, then it is helpful to introduce an auxiliary variable.
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
On line 2, an error is issued for a possible access via pointer to a value, although the area pointed to by the pointer is checked. If the value is first copied into a local variable and its range is checked, then the constant propagation can determine the range of values for that variable and allows access into the array on line 7.
Branching
For branching, individual branches are calculated separately. Value ranges from the individual ranges are then combined to form a new value range.
//Implementation IF func(TRUE) THEN x := 1; ELSE x := 10; END_IF IF func(FALSE) THEN y := x; ELSE Y := 2*x; END_IF
On line 6, x
has the range [1..10]
. After line 11, y
has the value range [1..20]
; this results from the union of the two value ranges [1..10]
and [2..20]
.
Conditions
Conditions can restrict the value range of a variable in a code block. Several conditions can be combined. Mutually exclusive conditions can also result in an empty value range.
IF y > 0 AND y < 10 THEN x := y; ELSE x:= 0; END_IF IF x < 0 THEN i := 99; END_IF
y has the value range [1..9]
on line 2. This results in the value range [0..9]
for x
on line 6. Combined with the condition x < 0
, this results in an empty set of possible values for x
on line 8. The code is not accessible. The static analysis will report that the condition x < 0
always returns FALSE
at this point.
Looping
Constant propagation will loop code until the values of the variables in the loop no longer change. It is assumed that a loop can be run any number of times. The values determined so far are combined with the previous values. Variables which are changed within the loop have a successively growing range. Here, the constant propagation does not take all possible values for ranges, but uses only limits which occur in the code and also the values 0, 1, 2, 3, and 10 because these are often relevant.
The simplest way to describe the procedure is by example:
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
The constant propagation knows the following about the loop:
i
, x
, and y
are 0 at the beginning of the first execution of the loop. The condition i <= 5
applies to the code in the loop. The condition i > 5
applies to the code after the loop.
For the values of the variables in the loop, the constant propagation determines the following values:
|
|
| ||
---|---|---|---|---|
|
|
|
In detail, the following intermediate steps are passed through:
Pass |
|
|
| |
---|---|---|---|---|
1 | 0 |
|
|
|
2 |
|
|
| |
6 |
|
|
| First, the range |
7 |
|
|
| |
10 |
|
|
|
|
11 |
|
|
|
|
As of 11 | From the 11th pass, the values in the loop will not change. The propagation is ended. |
Furthermore, i = 6
applies for the code following this loop. The range [0..6]
is determined in the loop and this is combined with the condition i > 5
, which results in exactly the value 6.