* fixed calling inline functions (with exit statements) from inside

finally blocks
  * fixed the handling of function results of inlined functions with
    exit statements
  + test for the above two issues and for bug fixed in r8091
  * copy may_be_in_reg field inside ttempcreatenode.dogetcopy (allows
    some more temps which were needlessly forced into memory to be in
    registers)

git-svn-id: trunk@8108 -
This commit is contained in:
Jonas Maebe 2007-07-20 16:49:35 +00:00
parent 20dbda751a
commit 49a2084ea0
7 changed files with 96 additions and 5 deletions

1
.gitattributes vendored
View File

@ -6880,6 +6880,7 @@ tests/test/tinline4.pp svneol=native#text/plain
tests/test/tinline5.pp -text
tests/test/tinline6.pp svneol=native#text/plain
tests/test/tinline7.pp svneol=native#text/plain
tests/test/tinline8.pp svneol=native#text/plain
tests/test/tint2str1.pp svneol=native#text/plain
tests/test/tint2str2.pp svneol=native#text/plain
tests/test/tint641.pp svneol=native#text/plain

View File

@ -111,6 +111,7 @@ interface
may_be_in_reg : boolean;
valid : boolean;
nextref_set_hookoncopy_nil : boolean;
is_inlined_result : boolean;
end;
{ a node which will create a (non)persistent temp of a given type with a given }
@ -127,6 +128,7 @@ interface
{ to it and *not* generate a ttempdeletenode }
constructor create(_typedef: tdef; _size: aint; _temptype: ttemptype;allowreg:boolean); virtual;
constructor create_withnode(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean; withnode: tnode); virtual;
constructor create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean); virtual;
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
procedure ppuwrite(ppufile:tcompilerppufile);override;
procedure buildderefimpl;override;
@ -736,6 +738,13 @@ implementation
end;
constructor ttempcreatenode.create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean);
begin
self.create(_typedef,_size,_temptype,allowreg);
tempinfo^.is_inlined_result:=true;
end;
function ttempcreatenode.dogetcopy: tnode;
var
n: ttempcreatenode;
@ -748,6 +757,8 @@ implementation
n.tempinfo^.owner:=n;
n.tempinfo^.typedef := tempinfo^.typedef;
n.tempinfo^.temptype := tempinfo^.temptype;
n.tempinfo^.may_be_in_reg := tempinfo^.may_be_in_reg;
n.tempinfo^.is_inlined_result := tempinfo^.is_inlined_result;
if assigned(tempinfo^.withnode) then
n.tempinfo^.withnode := tempinfo^.withnode.getcopy
else
@ -776,6 +787,7 @@ implementation
new(tempinfo);
fillchar(tempinfo^,sizeof(tempinfo^),0);
tempinfo^.may_be_in_reg:=boolean(ppufile.getbyte);
tempinfo^.is_inlined_result:=boolean(ppufile.getbyte);
ppufile.getderef(tempinfo^.typedefderef);
tempinfo^.temptype := ttemptype(ppufile.getbyte);
tempinfo^.owner:=self;
@ -788,6 +800,7 @@ implementation
inherited ppuwrite(ppufile);
ppufile.putlongint(size);
ppufile.putbyte(byte(tempinfo^.may_be_in_reg));
ppufile.putbyte(byte(tempinfo^.is_inlined_result));
ppufile.putderef(tempinfo^.typedefderef);
ppufile.putbyte(byte(tempinfo^.temptype));
ppuwritenode(ppufile,tempinfo^.withnode);
@ -847,6 +860,7 @@ implementation
inherited docompare(p) and
(ttempcreatenode(p).size = size) and
(ttempcreatenode(p).tempinfo^.may_be_in_reg = tempinfo^.may_be_in_reg) and
(ttempcreatenode(p).tempinfo^.is_inlined_result = tempinfo^.is_inlined_result) and
(ttempcreatenode(p).tempinfo^.withnode.isequal(tempinfo^.withnode)) and
equal_defs(ttempcreatenode(p).tempinfo^.typedef,tempinfo^.typedef);
end;

View File

@ -2450,15 +2450,19 @@ implementation
end
else
begin
tempnode := ctempcreatenode.create(tabstractvarsym(p).vardef,tabstractvarsym(p).vardef.size,tt_persistent,tabstractvarsym(p).is_regvar(false));
addstatement(tempinfo^.createstatement,tempnode);
if (vo_is_funcret in tlocalvarsym(p).varoptions) then
begin
tempnode := ctempcreatenode.create_inlined_result(tabstractvarsym(p).vardef,tabstractvarsym(p).vardef.size,tt_persistent,tabstractvarsym(p).is_regvar(false));
addstatement(tempinfo^.createstatement,tempnode);
funcretnode := ctemprefnode.create(tempnode);
addstatement(tempinfo^.deletestatement,ctempdeletenode.create_normal_temp(tempnode));
end
else
addstatement(tempinfo^.deletestatement,ctempdeletenode.create(tempnode));
begin
tempnode := ctempcreatenode.create(tabstractvarsym(p).vardef,tabstractvarsym(p).vardef.size,tt_persistent,tabstractvarsym(p).is_regvar(false));
addstatement(tempinfo^.createstatement,tempnode);
addstatement(tempinfo^.deletestatement,ctempdeletenode.create(tempnode));
end;
inlinelocals[indexnr] := ctemprefnode.create(tempnode);
end;
end;

View File

@ -334,6 +334,7 @@ interface
var
hp : tstatementnode;
oldexitlabel : tasmlabel;
oldflowcontrol : tflowcontrol;
begin
location_reset(location,LOC_VOID,OS_NO);
@ -342,6 +343,9 @@ interface
begin
oldexitlabel:=current_procinfo.CurrExitLabel;
current_asmdata.getjumplabel(current_procinfo.CurrExitLabel);
oldflowcontrol:=flowcontrol;
{ the nested block will not span an exit statement of the parent }
exclude(flowcontrol,fc_exit);
end;
{ do second pass on left node }
@ -365,6 +369,9 @@ interface
begin
cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
current_procinfo.CurrExitLabel:=oldexitlabel;
{ the exit statements inside this block are not exit statements }
{ out of the parent }
flowcontrol:=oldflowcontrol+(flowcontrol - [fc_exit]);
end;
end;

View File

@ -2502,7 +2502,9 @@ implementation
begin
if (ttemprefnode(n).tempinfo^.valid) and
(ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
(ttemprefnode(n).tempinfo^.location.register = rr^.old) then
(ttemprefnode(n).tempinfo^.location.register = rr^.old) and
(not ttemprefnode(n).tempinfo^.is_inlined_result or
not(fc_exit in flowcontrol)) then
begin
{$ifndef cpu64bit}
{ it's possible a 64 bit location was shifted and/xor typecasted }

View File

@ -43,7 +43,7 @@ type
{$endif Test_Double_checksum}
const
CurrentPPUVersion=81;
CurrentPPUVersion=82;
{ buffer sizes }
maxentrysize = 1024;

63
tests/test/tinline8.pp Normal file
View File

@ -0,0 +1,63 @@
{$ifdef fpc}
{$mode objfpc}
{$inline on}
{$endif}
uses
sysutils;
var a: longint;
function f(l: longint): longint; inline;
var
l1,l2,l3: longint;
begin
result:=123456;
if (l > 10) then
exit;
result:=30;
for l1 := 1 to 10 do
for l2 := 1 to 100 do
;
result := 40;
for l3 := 1 to 10 do;
end;
procedure test;
var
l: longint;
begin
l:= f(a);
if (l<>123456) then
halt(1);
end;
procedure test2;
var
l: longint;
begin
try
finally
l:= f(a);
if (l<>123456) then
halt(1);
end;
end;
procedure inl2; inline;
begin
try
except on exception do ;
end
end;
begin
a:=20;
test;
test2;
inl2
end.