mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 02:31:49 +01: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
	 Jonas Maebe
						Jonas Maebe