mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 14:49:17 +02:00
+ to000000.pp
This commit is contained in:
parent
52f38ed4a5
commit
ccd97bbec9
@ -28,3 +28,5 @@ ts010015.pp tests typed files.
|
|||||||
ts10100.pp tests for delphi object model
|
ts10100.pp tests for delphi object model
|
||||||
-
|
-
|
||||||
ts101xx.pp
|
ts101xx.pp
|
||||||
|
|
||||||
|
to000000 shows when uncertain optimizations can cause wrong code
|
||||||
|
53
tests/to000000.pp
Normal file
53
tests/to000000.pp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
Program UnsureOptsFail;
|
||||||
|
{This program shows how unsure optimizations can cause wrong code if you
|
||||||
|
program Silly Things (TM)
|
||||||
|
|
||||||
|
The principle is always the same:
|
||||||
|
|
||||||
|
you have a normal variable (local or global) and a pointer to it in one way
|
||||||
|
or another (be it a normal pointer or a var parameter).
|
||||||
|
|
||||||
|
a) you first cause the value from the memeory location to be loaded in a
|
||||||
|
register (e.g. by using the normal variable as an array index)
|
||||||
|
b) next you assign a new value to the memory location (e.g. through the
|
||||||
|
pointer)
|
||||||
|
c) finally, you compare the two values
|
||||||
|
|
||||||
|
Of course you can also use the pointer as an array index and assign a new
|
||||||
|
value to the normal variuable, that doesn't change anything).
|
||||||
|
|
||||||
|
The problem is that the value of the first load is still in a register, so
|
||||||
|
it isn't loaded from memory again, so you compare the old value with the
|
||||||
|
new one.
|
||||||
|
|
||||||
|
Note: this code doesn4t function correctly only when compiled with uncertain
|
||||||
|
optimizations on. All other forms of optimization are completely safe.
|
||||||
|
}
|
||||||
|
|
||||||
|
var l: longint;
|
||||||
|
p: ^longint;
|
||||||
|
a: Array[1..10] of byte;
|
||||||
|
|
||||||
|
Procedure ChangeIt(var t: longint);
|
||||||
|
{The same principle as in the main program, only here we have a var parameter
|
||||||
|
instead of a "normal" pointer. If l is passed to this procedure, it doesn't
|
||||||
|
function right.}
|
||||||
|
Begin
|
||||||
|
t := 1;
|
||||||
|
If t = l Then {t gets loaded in a register (eax)}
|
||||||
|
Begin
|
||||||
|
l := 2;
|
||||||
|
If t <> l then
|
||||||
|
Writeln('She can''t take any more or she''ll blow, captain!');
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
|
||||||
|
begin
|
||||||
|
p := @l; {p points to l}
|
||||||
|
l := 1;
|
||||||
|
a[p^] := 2; {load p^ in a register (eax in this case)}
|
||||||
|
l := 2; {change the value of l}
|
||||||
|
If p^ <> l
|
||||||
|
Then Writeln('Houston, we have a problem!');
|
||||||
|
ChangeIt(l);
|
||||||
|
End.
|
Loading…
Reference in New Issue
Block a user