Referencing fields or properties in ASM generates incorrect code
Original Reporter info from Mantis: ahydra
-
Reporter name: Colin Haywood
Original Reporter info from Mantis: ahydra
- Reporter name: Colin Haywood
Description:
Possibly related to https://bugs.freepascal.org/view.php?id=32318
See program in Steps to Reproduce section. The program prints "2" when it should print "1", as 5 is not bigger than 7.
The problem is that the line
CMP a.b, 7
is compiled as
cmpl $0x7,0x0(%rbp)
where 0x0(%rbp) doesn't refer to anything - the class instance pointer "a" is stored at -0x8(%rbp). (Though in the original case where I hit this, it was comparing against the class instance pointer.)
Since looking up a.b requires two operations (first to load the pointer a, and second to dereference with some offset to get the value of a.b), this code shouldn't compile at all (unless you fancied being clever in the case of "MOV reg, field" by replacing it with "MOV reg, instanceptr; MOV reg, DWORD/etc PTR [reg+offset]", but I don't see the point.)
The workaround is to read the field into a local variable before the asm, which works fine.
Steps to reproduce:
program Project1;
{$ASMMODE INTEL}
type
TA = class
b: integer;
end;
procedure Test();
var
a: TA;
r: integer;
begin
a := TA.Create();
a.b := 5;
asm
CMP a.b, 7
JG @Bigger
MOV r, 1
JMP @Exit
@Bigger:
MOV r, 2
@Exit:
end [];
writeln(r);
readln();
end;
begin
Test();
end.
Additional information:
See https://bugs.freepascal.org/view.php?id=32905 for why the program is written with a function call.
Mantis conversion info:
- Mantis ID: 32906
- OS: Windows
- OS Build: 7
- Platform: x64
- Version: 3.0.4
- Fixed in revision: 37886 (#1b669957)