mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-04 02:38:22 +02:00
* fixed location_free() for locations consisting of multiple
physical registers * free the physical return registers at the caller side for 64 bit systems * make sure that we do not double-free registers in case a return value is not used (mantis #13536) git-svn-id: trunk@13023 -
This commit is contained in:
parent
24ce200737
commit
a4bf91001e
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -8821,6 +8821,7 @@ tests/webtbs/tw13345x.pp svneol=native#text/plain
|
|||||||
tests/webtbs/tw13456.pp svneol=native#text/plain
|
tests/webtbs/tw13456.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw1348.pp svneol=native#text/plain
|
tests/webtbs/tw1348.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw1351.pp svneol=native#text/plain
|
tests/webtbs/tw1351.pp svneol=native#text/plain
|
||||||
|
tests/webtbs/tw13536.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw1364.pp svneol=native#text/plain
|
tests/webtbs/tw1364.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw1365.pp svneol=native#text/plain
|
tests/webtbs/tw1365.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw1374.pp svneol=native#text/plain
|
tests/webtbs/tw1374.pp svneol=native#text/plain
|
||||||
|
@ -538,11 +538,22 @@ implementation
|
|||||||
{$ifdef x86}
|
{$ifdef x86}
|
||||||
tcgx86(cg).inc_fpu_stack;
|
tcgx86(cg).inc_fpu_stack;
|
||||||
{$else x86}
|
{$else x86}
|
||||||
if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
|
{ Do not move the physical register to a virtual one in case
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
the return value is not used, because if the virtual one is
|
||||||
hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
|
then mapped to the same register as the physical one, we will
|
||||||
cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
|
end up with two deallocs of this register (one inserted here,
|
||||||
location.register:=hregister;
|
one inserted by the register allocator), which unbalances the
|
||||||
|
register allocation information. The return register(s) will
|
||||||
|
be freed by location_free() in release_unused_return_value
|
||||||
|
(mantis #13536). }
|
||||||
|
if (cnf_return_value_used in callnodeflags) then
|
||||||
|
begin
|
||||||
|
if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
|
||||||
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
||||||
|
hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
|
||||||
|
cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
|
||||||
|
location.register:=hregister;
|
||||||
|
end;
|
||||||
{$endif x86}
|
{$endif x86}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -556,12 +567,25 @@ implementation
|
|||||||
structs with up to 16 bytes are returned in registers }
|
structs with up to 16 bytes are returned in registers }
|
||||||
if cgsize in [OS_128,OS_S128] then
|
if cgsize in [OS_128,OS_S128] then
|
||||||
begin
|
begin
|
||||||
tg.GetTemp(current_asmdata.CurrAsmList,16,8,tt_normal,ref);
|
retloc:=procdefinition.funcretloc[callerside];
|
||||||
location_reset_ref(location,LOC_REFERENCE,OS_NO,0);
|
if retloc.loc<>LOC_REGISTER then
|
||||||
location.reference:=ref;
|
internalerror(2009042001);
|
||||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_64,OS_64,procdefinition.funcretloc[callerside].register,ref);
|
{ See #13536 comment above. }
|
||||||
inc(ref.offset,8);
|
if (cnf_return_value_used in callnodeflags) then
|
||||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_64,OS_64,procdefinition.funcretloc[callerside].registerhi,ref);
|
begin
|
||||||
|
tg.GetTemp(current_asmdata.CurrAsmList,16,8,tt_normal,ref);
|
||||||
|
location_reset_ref(location,LOC_REFERENCE,OS_NO,0);
|
||||||
|
location.reference:=ref;
|
||||||
|
if getsupreg(retloc.register)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register);
|
||||||
|
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_64,OS_64,retloc.register,ref);
|
||||||
|
inc(ref.offset,8);
|
||||||
|
if getsupreg(retloc.registerhi)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.registerhi);
|
||||||
|
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_64,OS_64,retloc.registerhi,ref);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
location:=retloc;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
{$else cpu64bitaddr}
|
{$else cpu64bitaddr}
|
||||||
@ -570,15 +594,21 @@ implementation
|
|||||||
retloc:=procdefinition.funcretloc[callerside];
|
retloc:=procdefinition.funcretloc[callerside];
|
||||||
if retloc.loc<>LOC_REGISTER then
|
if retloc.loc<>LOC_REGISTER then
|
||||||
internalerror(200409141);
|
internalerror(200409141);
|
||||||
{ the function result registers are already allocated }
|
{ See #13536 comment above. }
|
||||||
if getsupreg(retloc.register64.reglo)<first_int_imreg then
|
if (cnf_return_value_used in callnodeflags) then
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
|
begin
|
||||||
location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
{ the function result registers are already allocated }
|
||||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
|
if getsupreg(retloc.register64.reglo)<first_int_imreg then
|
||||||
if getsupreg(retloc.register64.reghi)<first_int_imreg then
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
|
location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||||
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
|
||||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
|
if getsupreg(retloc.register64.reghi)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
|
||||||
|
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
|
||||||
|
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
location:=retloc;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
{$endif not cpu64bitaddr}
|
{$endif not cpu64bitaddr}
|
||||||
@ -588,19 +618,25 @@ implementation
|
|||||||
def_cgsize(resultdef) is used here because
|
def_cgsize(resultdef) is used here because
|
||||||
it could be a constructor call }
|
it could be a constructor call }
|
||||||
|
|
||||||
if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
|
{ See #13536 comment above. }
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
if (cnf_return_value_used in callnodeflags) then
|
||||||
|
begin
|
||||||
|
if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
||||||
|
|
||||||
{ but use def_size only if it returns something valid because in
|
{ but use def_size only if it returns something valid because in
|
||||||
case of odd sized structured results in registers def_cgsize(resultdef)
|
case of odd sized structured results in registers def_cgsize(resultdef)
|
||||||
could return OS_NO }
|
could return OS_NO }
|
||||||
if def_cgsize(resultdef)<>OS_NO then
|
if def_cgsize(resultdef)<>OS_NO then
|
||||||
tmpcgsize:=def_cgsize(resultdef)
|
tmpcgsize:=def_cgsize(resultdef)
|
||||||
|
else
|
||||||
|
tmpcgsize:=cgsize;
|
||||||
|
|
||||||
|
location.register:=cg.getintregister(current_asmdata.CurrAsmList,tmpcgsize);
|
||||||
|
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,tmpcgsize,procdefinition.funcretloc[callerside].register,location.register);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
tmpcgsize:=cgsize;
|
location:=procdefinition.funcretloc[callerside];
|
||||||
|
|
||||||
location.register:=cg.getintregister(current_asmdata.CurrAsmList,tmpcgsize);
|
|
||||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,tmpcgsize,procdefinition.funcretloc[callerside].register,location.register);
|
|
||||||
end;
|
end;
|
||||||
{$ifdef arm}
|
{$ifdef arm}
|
||||||
if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
|
if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
|
||||||
@ -618,11 +654,17 @@ implementation
|
|||||||
|
|
||||||
LOC_MMREGISTER:
|
LOC_MMREGISTER:
|
||||||
begin
|
begin
|
||||||
location_reset(location,LOC_MMREGISTER,cgsize);
|
{ See #13536 comment above. }
|
||||||
if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
|
if (cnf_return_value_used in callnodeflags) then
|
||||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
begin
|
||||||
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,cgsize);
|
location_reset(location,LOC_MMREGISTER,cgsize);
|
||||||
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
|
if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
|
||||||
|
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
|
||||||
|
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,cgsize);
|
||||||
|
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
location:=procdefinition.funcretloc[callerside];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -185,8 +185,28 @@ implementation
|
|||||||
LOC_REGISTER,
|
LOC_REGISTER,
|
||||||
LOC_CREGISTER:
|
LOC_CREGISTER:
|
||||||
begin
|
begin
|
||||||
if getsupreg(location.register)<first_int_imreg then
|
{$ifdef cpu64bitaddr}
|
||||||
cg.ungetcpuregister(list,location.register);
|
{ x86-64 system v abi:
|
||||||
|
structs with up to 16 bytes are returned in registers }
|
||||||
|
if location.size in [OS_128,OS_S128] then
|
||||||
|
begin
|
||||||
|
if getsupreg(location.register)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(list,location.register);
|
||||||
|
if getsupreg(location.registerhi)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(list,location.registerhi);
|
||||||
|
end
|
||||||
|
{$else cpu64bitaddr}
|
||||||
|
if location.size in [OS_64,OS_S64] then
|
||||||
|
begin
|
||||||
|
if getsupreg(location.register64.reglo)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(list,location.register64.reglo);
|
||||||
|
if getsupreg(location.register64.reghi)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(list,location.register64.reghi);
|
||||||
|
end
|
||||||
|
{$endif}
|
||||||
|
else
|
||||||
|
if getsupreg(location.register)<first_int_imreg then
|
||||||
|
cg.ungetcpuregister(list,location.register);
|
||||||
end;
|
end;
|
||||||
LOC_FPUREGISTER,
|
LOC_FPUREGISTER,
|
||||||
LOC_CFPUREGISTER:
|
LOC_CFPUREGISTER:
|
||||||
|
87
tests/webtbs/tw13536.pp
Normal file
87
tests/webtbs/tw13536.pp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
|
||||||
|
// without -O3 prints 0002020200010101
|
||||||
|
// with -O3 prints 0001010100010101
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
uses sysutils;
|
||||||
|
|
||||||
|
Const
|
||||||
|
MAXDWORD = $FFFFFFFF;
|
||||||
|
|
||||||
|
|
||||||
|
Type
|
||||||
|
Filetime=longint;
|
||||||
|
tchar=char;
|
||||||
|
XWIN32_FIND_DATA = record
|
||||||
|
dwFileAttributes : DWORD;
|
||||||
|
ftLastWriteTime : FILETIME;
|
||||||
|
nFileSizeHigh : DWORD;
|
||||||
|
nFileSizeLow : DWORD;
|
||||||
|
cFileName : array[0..(MAX_PATH)-1] of TCHAR;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Type
|
||||||
|
TMySearchRec = Record
|
||||||
|
Time : Longint;
|
||||||
|
Size : Int64;
|
||||||
|
Attr : Longint;
|
||||||
|
Name : TFileName;
|
||||||
|
ExcludeAttr : Longint;
|
||||||
|
FindHandle : THandle;
|
||||||
|
FindData : XWIN32_FIND_DATA;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function getlasterror:integer;
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
|
||||||
|
function aFindNextFile (F:thandle;fd:XWIN32_FIND_DATA):boolean;
|
||||||
|
begin
|
||||||
|
|
||||||
|
end;
|
||||||
|
|
||||||
|
function WinToDosTime( Var Wtime : FileTime;var DTime:longint):longbool;
|
||||||
|
begin
|
||||||
|
end;
|
||||||
|
|
||||||
|
Function aFindMatch(var f: TMySearchRec) : Longint;
|
||||||
|
begin
|
||||||
|
// commenting code before the f.size:= line seems to alter the behaviour
|
||||||
|
{ Find file with correct attribute }
|
||||||
|
While (F.FindData.dwFileAttributes and cardinal(F.ExcludeAttr))<>0 do
|
||||||
|
begin
|
||||||
|
if not aFindNextFile (F.FindHandle,F.FindData) then
|
||||||
|
begin
|
||||||
|
Result:=GetLastError;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Convert some attributes back }
|
||||||
|
WinToDosTime(F.FindData.ftLastWriteTime,F.Time);
|
||||||
|
|
||||||
|
f.size:=F.FindData.NFileSizeLow+(qword(maxdword)+1)*F.FindData.NFileSizeHigh;
|
||||||
|
f.attr:=F.FindData.dwFileAttributes;
|
||||||
|
f.Name:=StrPas(@F.FindData.cFileName[0]);
|
||||||
|
Result:=0;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var n : TMySearchRec;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// make sure it gets past the while loop.
|
||||||
|
n.finddata.dwfileattributes:=1;
|
||||||
|
n.excludeattr:=0;
|
||||||
|
|
||||||
|
n.FindData.NFileSizeLow:=$10101;
|
||||||
|
n.FindData.NFileSizehigh:=$20202;
|
||||||
|
// attempt to avoid problems with strpas.
|
||||||
|
n.finddata.cfilename:='bla'#0;
|
||||||
|
aFindMatch(n);
|
||||||
|
|
||||||
|
writeln(n.size);
|
||||||
|
writeln(inttohex(n.size,16));
|
||||||
|
if (n.size<>$0002020200010101) then
|
||||||
|
halt(1);
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user