|
@@ -0,0 +1,72 @@
|
|
|
|
+{ $OPT=-OG2}
|
|
|
|
+{$r+}
|
|
|
|
+
|
|
|
|
+type
|
|
|
|
+ tsubr = 1..100000;
|
|
|
|
+ tarr = array[1..10] of longint;
|
|
|
|
+
|
|
|
|
+function test(b: tsubr): longint;
|
|
|
|
+begin
|
|
|
|
+ test := b;
|
|
|
|
+end;
|
|
|
|
+
|
|
|
|
+var
|
|
|
|
+ p: ^longint;
|
|
|
|
+ l: longint;
|
|
|
|
+ a, a2: tarr;
|
|
|
|
+
|
|
|
|
+begin
|
|
|
|
+ getmem(p,4);
|
|
|
|
+ p^ := 100000;
|
|
|
|
+ l := 5;
|
|
|
|
+ { clear the optimizer state }
|
|
|
|
+ asm
|
|
|
|
+ end;
|
|
|
|
+{$r-}
|
|
|
|
+ { get p^ in eax, the following statement generates the code }
|
|
|
|
+ { movl A,%eax }
|
|
|
|
+ { movl (%eax),%eax }
|
|
|
|
+ a[p^] := l;
|
|
|
|
+{$r+}
|
|
|
|
+ { now, p^ gets rangechecked, this generates the code }
|
|
|
|
+ { movl A,%eax (1) }
|
|
|
|
+ { movl (%eax),%ecx (1) }
|
|
|
|
+ { ... }
|
|
|
|
+ { call rangecheck_procedure }
|
|
|
|
+ { pushl (%eax) }
|
|
|
|
+ { }
|
|
|
|
+ { With the bug in the optimizer, the instructions marked with (1) are }
|
|
|
|
+ { replaced by }
|
|
|
|
+ { movl %eax,%ecx }
|
|
|
|
+ { }
|
|
|
|
+ { and as such the "pushl (%eax)" pushes a wrong value afterwards }
|
|
|
|
+ l := test(p^);
|
|
|
|
+ if l <> 100000 then
|
|
|
|
+ begin
|
|
|
|
+ writeln('Problem 1!');
|
|
|
|
+ halt(1);
|
|
|
|
+ end;
|
|
|
|
+ p^ := 5;
|
|
|
|
+ l := 5;
|
|
|
|
+ { clear the optimizer state }
|
|
|
|
+ asm
|
|
|
|
+ end;
|
|
|
|
+{$r-}
|
|
|
|
+ { the following moves p^ in %edx }
|
|
|
|
+ a2[l] := a[p^];
|
|
|
|
+{$r+}
|
|
|
|
+ { same test as before, but now the original value comes from edx }
|
|
|
|
+ { instead of that it is already in eax (so check that it doesn't }
|
|
|
|
+ { replace the }
|
|
|
|
+ { movl P,%eax }
|
|
|
|
+ { movl (%eax),%ecx }
|
|
|
|
+ { with }
|
|
|
|
+ { movl %edx,%ecx }
|
|
|
|
+ l := test(p^);
|
|
|
|
+ if l <> 5 then
|
|
|
|
+ begin
|
|
|
|
+ writeln('Problem 2!');
|
|
|
|
+ halt(1);
|
|
|
|
+ end;
|
|
|
|
+ freemem(p,4);
|
|
|
|
+end.
|