summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-07-20 16:49:35 +0000
committerjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2007-07-20 16:49:35 +0000
commitc5f6f902a774546ef465f1ee21a15bd277b98560 (patch)
tree90bb4108a633ca82ba16834f3859ad96ae8a69b8
parent3eaed0468cba68a3b003e986280be2e18029b653 (diff)
downloadfpc-c5f6f902a774546ef465f1ee21a15bd277b98560.tar.gz
* 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: http://svn.freepascal.org/svn/fpc/trunk@8108 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--compiler/nbas.pas14
-rw-r--r--compiler/ncal.pas10
-rw-r--r--compiler/ncgbas.pas7
-rw-r--r--compiler/ncgutil.pas4
-rw-r--r--compiler/ppu.pas2
-rw-r--r--tests/test/tinline8.pp63
6 files changed, 95 insertions, 5 deletions
diff --git a/compiler/nbas.pas b/compiler/nbas.pas
index 7edca18799..5137200f42 100644
--- a/compiler/nbas.pas
+++ b/compiler/nbas.pas
@@ -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;
diff --git a/compiler/ncal.pas b/compiler/ncal.pas
index 5e4a038943..fb47944eba 100644
--- a/compiler/ncal.pas
+++ b/compiler/ncal.pas
@@ -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;
diff --git a/compiler/ncgbas.pas b/compiler/ncgbas.pas
index 86b9f49d7f..ec8e6d0527 100644
--- a/compiler/ncgbas.pas
+++ b/compiler/ncgbas.pas
@@ -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;
diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas
index 598445c32f..c6a6ad60f5 100644
--- a/compiler/ncgutil.pas
+++ b/compiler/ncgutil.pas
@@ -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 }
diff --git a/compiler/ppu.pas b/compiler/ppu.pas
index 783829dc87..f176fedfb3 100644
--- a/compiler/ppu.pas
+++ b/compiler/ppu.pas
@@ -43,7 +43,7 @@ type
{$endif Test_Double_checksum}
const
- CurrentPPUVersion=81;
+ CurrentPPUVersion=82;
{ buffer sizes }
maxentrysize = 1024;
diff --git a/tests/test/tinline8.pp b/tests/test/tinline8.pp
new file mode 100644
index 0000000000..3536fd7271
--- /dev/null
+++ b/tests/test/tinline8.pp
@@ -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.