diff options
author | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2007-07-20 16:49:35 +0000 |
---|---|---|
committer | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2007-07-20 16:49:35 +0000 |
commit | c5f6f902a774546ef465f1ee21a15bd277b98560 (patch) | |
tree | 90bb4108a633ca82ba16834f3859ad96ae8a69b8 | |
parent | 3eaed0468cba68a3b003e986280be2e18029b653 (diff) | |
download | fpc-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.pas | 14 | ||||
-rw-r--r-- | compiler/ncal.pas | 10 | ||||
-rw-r--r-- | compiler/ncgbas.pas | 7 | ||||
-rw-r--r-- | compiler/ncgutil.pas | 4 | ||||
-rw-r--r-- | compiler/ppu.pas | 2 | ||||
-rw-r--r-- | tests/test/tinline8.pp | 63 |
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. |