mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-04 09:30:47 +02:00
* 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:
parent
20dbda751a
commit
49a2084ea0
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 }
|
||||
|
@ -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
63
tests/test/tinline8.pp
Normal 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.
|
Loading…
Reference in New Issue
Block a user