From 4b7f92a367b3b49cec6e41f8edb8ad4409a5719e Mon Sep 17 00:00:00 2001 From: svenbarth Date: Sat, 1 May 2021 15:48:45 +0000 Subject: [PATCH] Merged revision(s) 48972, 49057 from trunk: + tx64tryfinallynode.dogetcopy properly implemented, resolves #37305 ........ * patch by Do-wan Kim: fix loop unrolling for try .. finally blocks in win32, similiar to r48972 for win64 ........ git-svn-id: branches/fixes_3_2@49316 - --- .gitattributes | 2 ++ compiler/i386/n386flw.pas | 30 ++++++++++++++++++-- compiler/x86_64/nx64flw.pas | 56 ++++++++++++++++++++++++++++++------- tests/webtbs/tw37305a.pp | 13 +++++++++ tests/webtbs/tw37305b.pp | 12 ++++++++ 5 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 tests/webtbs/tw37305a.pp create mode 100644 tests/webtbs/tw37305b.pp diff --git a/.gitattributes b/.gitattributes index d6b7afde95..e3aea53ab6 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17803,6 +17803,8 @@ tests/webtbs/tw3719.pp svneol=native#text/plain tests/webtbs/tw3721.pp svneol=native#text/plain tests/webtbs/tw37218.pp svneol=native#text/pascal tests/webtbs/tw37228.pp svneol=native#text/plain +tests/webtbs/tw37305a.pp svneol=native#text/pascal +tests/webtbs/tw37305b.pp svneol=native#text/pascal tests/webtbs/tw37322.pp svneol=native#text/pascal tests/webtbs/tw37323.pp svneol=native#text/pascal tests/webtbs/tw37355.pp svneol=native#text/pascal diff --git a/compiler/i386/n386flw.pas b/compiler/i386/n386flw.pas index 6c47a2c20a..08d96fa89c 100644 --- a/compiler/i386/n386flw.pas +++ b/compiler/i386/n386flw.pas @@ -46,6 +46,7 @@ interface constructor create(l,r:TNode);override; constructor create_implicit(l,r:TNode);override; function pass_1: tnode;override; + function dogetcopy : tnode;override; function simplify(forinline: boolean): tnode;override; procedure pass_generate_code;override; end; @@ -59,7 +60,7 @@ implementation cgbase,cgobj,cgcpu,cgutils,tgobj, cpubase,htypechk, parabase,paramgr,pass_1,pass_2,ncgutil,cga, - aasmbase,aasmtai,aasmdata,aasmcpu,procinfo,cpupi; + aasmbase,aasmtai,aasmdata,aasmcpu,procinfo,cpupi,procdefutil; var endexceptlabel: tasmlabel; @@ -215,6 +216,30 @@ function ti386tryfinallynode.pass_1: tnode; end; end; +function ti386tryfinallynode.dogetcopy: tnode; + var + n: ti386tryfinallynode; + begin + n:=ti386tryfinallynode(inherited dogetcopy); + if target_info.system=system_i386_win32 then + begin + n.finalizepi:=tcgprocinfo(cprocinfo.create(finalizepi.parent)); + n.finalizepi.force_nested; + n.finalizepi.procdef:=create_outline_procdef('$fin$',current_procinfo.procdef.struct,potype_exceptfilter,voidtype); + n.finalizepi.entrypos:=finalizepi.entrypos; + n.finalizepi.entryswitches:=finalizepi.entryswitches; + n.finalizepi.exitpos:=finalizepi.exitpos; + n.finalizepi.exitswitches:=finalizepi.exitswitches; + n.finalizepi.flags:=finalizepi.flags; + { node already transformed? } + if assigned(finalizepi.code) then + begin + n.finalizepi.code:=finalizepi.code.getcopy; + n.right:=ccallnode.create(nil,tprocsym(n.finalizepi.procdef.procsym),nil,nil,[],nil); + end; + end; + result:=n; + end; function ti386tryfinallynode.simplify(forinline: boolean): tnode; begin @@ -222,7 +247,8 @@ function ti386tryfinallynode.simplify(forinline: boolean): tnode; if (target_info.system<>system_i386_win32) then exit; - if (result=nil) and assigned(finalizepi) then + { actually, this is not really the right place to do a node transformation like this } + if (result=nil) and assigned(finalizepi) and (not(assigned(finalizepi.code))) then begin finalizepi.code:=right; foreachnodestatic(right,@copy_parasize,finalizepi); diff --git a/compiler/x86_64/nx64flw.pas b/compiler/x86_64/nx64flw.pas index 84f97a9f73..58994b4eed 100644 --- a/compiler/x86_64/nx64flw.pas +++ b/compiler/x86_64/nx64flw.pas @@ -45,6 +45,7 @@ interface finalizepi: tcgprocinfo; constructor create(l,r:TNode);override; constructor create_implicit(l,r:TNode);override; + function dogetcopy : tnode;override; function simplify(forinline: boolean): tnode;override; procedure pass_generate_code;override; end; @@ -58,7 +59,8 @@ implementation cgbase,cgobj,cgutils,tgobj, cpubase,htypechk, pass_1,pass_2, - aasmbase,aasmtai,aasmdata,aasmcpu,procinfo,cpupi; + aasmbase,aasmtai,aasmdata,aasmcpu, + procinfo,cpupi,procdefutil; var endexceptlabel: tasmlabel; @@ -169,6 +171,7 @@ constructor tx64tryfinallynode.create(l, r: TNode); end; end; + constructor tx64tryfinallynode.create_implicit(l, r: TNode); begin inherited create_implicit(l, r); @@ -185,6 +188,33 @@ constructor tx64tryfinallynode.create_implicit(l, r: TNode); end; end; + +function tx64tryfinallynode.dogetcopy: tnode; + var + n: tx64tryfinallynode; + begin + n:=tx64tryfinallynode(inherited dogetcopy); + if target_info.system=system_x86_64_win64 then + begin + n.finalizepi:=tcgprocinfo(cprocinfo.create(finalizepi.parent)); + n.finalizepi.force_nested; + n.finalizepi.procdef:=create_outline_procdef('$fin$',current_procinfo.procdef.struct,potype_exceptfilter,voidtype); + n.finalizepi.entrypos:=finalizepi.entrypos; + n.finalizepi.entryswitches:=finalizepi.entryswitches; + n.finalizepi.exitpos:=finalizepi.exitpos; + n.finalizepi.exitswitches:=finalizepi.exitswitches; + n.finalizepi.flags:=finalizepi.flags; + { node already transformed? } + if assigned(finalizepi.code) then + begin + n.finalizepi.code:=finalizepi.code.getcopy; + n.right:=ccallnode.create(nil,tprocsym(n.finalizepi.procdef.procsym),nil,nil,[],nil); + end; + end; + result:=n; + end; + + function tx64tryfinallynode.simplify(forinline: boolean): tnode; begin result:=inherited simplify(forinline); @@ -192,22 +222,27 @@ function tx64tryfinallynode.simplify(forinline: boolean): tnode; exit; if (result=nil) then begin - finalizepi.code:=right; - foreachnodestatic(right,@copy_parasize,finalizepi); - right:=ccallnode.create(nil,tprocsym(finalizepi.procdef.procsym),nil,nil,[],nil); - firstpass(right); - { For implicit frames, no actual code is available at this time, - it is added later in assembler form. So store the nested procinfo - for later use. } - if implicitframe then + { actually, this is not really the right place to do a node transformation like this } + if not(assigned(finalizepi.code)) then begin - current_procinfo.finalize_procinfo:=finalizepi; + finalizepi.code:=right; + foreachnodestatic(right,@copy_parasize,finalizepi); + right:=ccallnode.create(nil,tprocsym(finalizepi.procdef.procsym),nil,nil,[],nil); + firstpass(right); + { For implicit frames, no actual code is available at this time, + it is added later in assembler form. So store the nested procinfo + for later use. } + if implicitframe then + begin + current_procinfo.finalize_procinfo:=finalizepi; + end; { don't leave dangling pointer } tcgprocinfo(current_procinfo).final_asmnode:=nil; end; end; end; + procedure emit_nop; var dummy: TAsmLabel; @@ -219,6 +254,7 @@ procedure emit_nop; current_asmdata.CurrAsmList.concat(Taicpu.op_none(A_NOP,S_NO)); end; + procedure tx64tryfinallynode.pass_generate_code; var trylabel, diff --git a/tests/webtbs/tw37305a.pp b/tests/webtbs/tw37305a.pp new file mode 100644 index 0000000000..b07f0d4630 --- /dev/null +++ b/tests/webtbs/tw37305a.pp @@ -0,0 +1,13 @@ +{$mode objfpc} +var + i, j, c: Int32; +begin + c := 1; + for i := 0 to c do // SIGSEGV at runtime + try + j := i; + finally + if (j <> 0) then + j := 0; + end; +end. diff --git a/tests/webtbs/tw37305b.pp b/tests/webtbs/tw37305b.pp new file mode 100644 index 0000000000..dd39eb1769 --- /dev/null +++ b/tests/webtbs/tw37305b.pp @@ -0,0 +1,12 @@ +{$mode objfpc} +var + i, j: Int32; +begin + for i := 0 to 1 do // Error: Compilation raised exception internally + try + j := i; + finally + if (j <> 0) then + j := 0; + end; +end.