From 146a819615f5d41f78e87c5e19d7a8b8c971d4a9 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Fri, 21 Aug 2009 16:20:16 +0000 Subject: [PATCH] * fixed spilling of and operations on spilled 32 bit values for x86_64 (mantis #14403) git-svn-id: trunk@13573 - --- .gitattributes | 1 + compiler/x86/aasmcpu.pas | 18 ++++++++++++++- compiler/x86/rgx86.pas | 11 +++++++++- tests/webtbs/tw14403.pp | 47 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/webtbs/tw14403.pp diff --git a/.gitattributes b/.gitattributes index 7fab414328..696b9bf00f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9238,6 +9238,7 @@ tests/webtbs/tw1430.pp svneol=native#text/plain tests/webtbs/tw14307.pp svneol=native#text/plain tests/webtbs/tw1433.pp svneol=native#text/plain tests/webtbs/tw14363.pp svneol=native#text/plain +tests/webtbs/tw14403.pp svneol=native#text/plain tests/webtbs/tw1445.pp svneol=native#text/plain tests/webtbs/tw1450.pp svneol=native#text/plain tests/webtbs/tw1451.pp svneol=native#text/plain diff --git a/compiler/x86/aasmcpu.pas b/compiler/x86/aasmcpu.pas index 6ef6f9e7b0..258378b2ff 100644 --- a/compiler/x86/aasmcpu.pas +++ b/compiler/x86/aasmcpu.pas @@ -2402,6 +2402,8 @@ implementation begin case getregtype(r) of R_INTREGISTER : + { we don't need special code here for 32 bit loads on x86_64, since + those will automatically zero-extend the upper 32 bits. } result:=taicpu.op_ref_reg(A_MOV,reg2opsize(r),ref,r); R_MMREGISTER : case getsubreg(r) of @@ -2421,10 +2423,24 @@ implementation function spilling_create_store(r:tregister; const ref:treference):Taicpu; + var + size: topsize; begin case getregtype(r) of R_INTREGISTER : - result:=taicpu.op_reg_ref(A_MOV,reg2opsize(r),r,ref); + begin + size:=reg2opsize(r); +{$ifdef x86_64} + { even if it's a 32 bit reg, we still have to spill 64 bits + because we often perform 64 bit operations on them } + if (size=S_L) then + begin + size:=S_Q; + r:=newreg(getregtype(r),getsupreg(r),R_SUBWHOLE); + end; +{$endif x86_64} + result:=taicpu.op_reg_ref(A_MOV,size,r,ref); + end; R_MMREGISTER : case getsubreg(r) of R_SUBMMD: diff --git a/compiler/x86/rgx86.pas b/compiler/x86/rgx86.pas index 005c8bd7b0..08d6dae598 100644 --- a/compiler/x86/rgx86.pas +++ b/compiler/x86/rgx86.pas @@ -247,7 +247,16 @@ implementation end; end; end; - end; + end; + + {$ifdef x86_64} + { 32 bit operations on 32 bit registers on x86_64 can result in + zeroing the upper 32 bits of the register. This does not happen + with memory operations, so we have to perform these calculations + in registers. } + if (instr.opsize=S_L) then + replaceoper:=-1; + {$endif x86_64} { Replace register with spill reference } if replaceoper<>-1 then diff --git a/tests/webtbs/tw14403.pp b/tests/webtbs/tw14403.pp new file mode 100644 index 0000000000..45cf434f00 --- /dev/null +++ b/tests/webtbs/tw14403.pp @@ -0,0 +1,47 @@ +{$R+} +{$mode objfpc} + +type + TDummyShapeTree = class + function ShapesCount(const OnlyActive, OnlyVisible, OnlyCollidable: boolean): Cardinal; virtual; abstract; + end; + + TDummyShapeTreeGroup = class(TDummyShapeTree) + public + Child: TDummyShapeTree; + + function ShapesCount(const OnlyActive, OnlyVisible, OnlyCollidable: boolean): Cardinal; override; + end; + + TDummyShape = class(TDummyShapeTree) + public + function ShapesCount(const OnlyActive, OnlyVisible, OnlyCollidable: boolean): Cardinal; override; + end; + +function TDummyShape.ShapesCount( + const OnlyActive, OnlyVisible, OnlyCollidable: boolean): Cardinal; +begin + Result := 1; +end; + +function TDummyShapeTreeGroup.ShapesCount( + const OnlyActive, OnlyVisible, OnlyCollidable: boolean): Cardinal; +var + I: Integer; + Something: Cardinal; +begin + Result := 0; + for I := 0 to 1 do + begin + Result := Result + Child.ShapesCount(OnlyActive, OnlyVisible, OnlyCollidable); + end; +end; + +var + G: TDummyShapeTreeGroup; +begin + G := TDummyShapeTreeGroup.Create; + G.Child := TDummyShape.Create; + Writeln(G.ShapesCount(true, true, false)); + G.Free; +end.