فهرست منبع

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 -

svenbarth 4 سال پیش
والد
کامیت
4b7f92a367
5فایلهای تغییر یافته به همراه101 افزوده شده و 12 حذف شده
  1. 2 0
      .gitattributes
  2. 28 2
      compiler/i386/n386flw.pas
  3. 46 10
      compiler/x86_64/nx64flw.pas
  4. 13 0
      tests/webtbs/tw37305a.pp
  5. 12 0
      tests/webtbs/tw37305b.pp

+ 2 - 0
.gitattributes

@@ -17803,6 +17803,8 @@ tests/webtbs/tw3719.pp svneol=native#text/plain
 tests/webtbs/tw3721.pp svneol=native#text/plain
 tests/webtbs/tw3721.pp svneol=native#text/plain
 tests/webtbs/tw37218.pp svneol=native#text/pascal
 tests/webtbs/tw37218.pp svneol=native#text/pascal
 tests/webtbs/tw37228.pp svneol=native#text/plain
 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/tw37322.pp svneol=native#text/pascal
 tests/webtbs/tw37323.pp svneol=native#text/pascal
 tests/webtbs/tw37323.pp svneol=native#text/pascal
 tests/webtbs/tw37355.pp svneol=native#text/pascal
 tests/webtbs/tw37355.pp svneol=native#text/pascal

+ 28 - 2
compiler/i386/n386flw.pas

@@ -46,6 +46,7 @@ interface
       constructor create(l,r:TNode);override;
       constructor create(l,r:TNode);override;
       constructor create_implicit(l,r:TNode);override;
       constructor create_implicit(l,r:TNode);override;
       function pass_1: tnode;override;
       function pass_1: tnode;override;
+	  function dogetcopy : tnode;override;
       function simplify(forinline: boolean): tnode;override;
       function simplify(forinline: boolean): tnode;override;
       procedure pass_generate_code;override;
       procedure pass_generate_code;override;
     end;
     end;
@@ -59,7 +60,7 @@ implementation
     cgbase,cgobj,cgcpu,cgutils,tgobj,
     cgbase,cgobj,cgcpu,cgutils,tgobj,
     cpubase,htypechk,
     cpubase,htypechk,
     parabase,paramgr,pass_1,pass_2,ncgutil,cga,
     parabase,paramgr,pass_1,pass_2,ncgutil,cga,
-    aasmbase,aasmtai,aasmdata,aasmcpu,procinfo,cpupi;
+    aasmbase,aasmtai,aasmdata,aasmcpu,procinfo,cpupi,procdefutil;
 
 
   var
   var
     endexceptlabel: tasmlabel;
     endexceptlabel: tasmlabel;
@@ -215,6 +216,30 @@ function ti386tryfinallynode.pass_1: tnode;
       end;
       end;
   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;
 function ti386tryfinallynode.simplify(forinline: boolean): tnode;
   begin
   begin
@@ -222,7 +247,8 @@ function ti386tryfinallynode.simplify(forinline: boolean): tnode;
     if (target_info.system<>system_i386_win32) then
     if (target_info.system<>system_i386_win32) then
       exit;
       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
       begin
         finalizepi.code:=right;
         finalizepi.code:=right;
         foreachnodestatic(right,@copy_parasize,finalizepi);
         foreachnodestatic(right,@copy_parasize,finalizepi);

+ 46 - 10
compiler/x86_64/nx64flw.pas

@@ -45,6 +45,7 @@ interface
       finalizepi: tcgprocinfo;
       finalizepi: tcgprocinfo;
       constructor create(l,r:TNode);override;
       constructor create(l,r:TNode);override;
       constructor create_implicit(l,r:TNode);override;
       constructor create_implicit(l,r:TNode);override;
+      function dogetcopy : tnode;override;
       function simplify(forinline: boolean): tnode;override;
       function simplify(forinline: boolean): tnode;override;
       procedure pass_generate_code;override;
       procedure pass_generate_code;override;
     end;
     end;
@@ -58,7 +59,8 @@ implementation
     cgbase,cgobj,cgutils,tgobj,
     cgbase,cgobj,cgutils,tgobj,
     cpubase,htypechk,
     cpubase,htypechk,
     pass_1,pass_2,
     pass_1,pass_2,
-    aasmbase,aasmtai,aasmdata,aasmcpu,procinfo,cpupi;
+    aasmbase,aasmtai,aasmdata,aasmcpu,
+    procinfo,cpupi,procdefutil;
 
 
   var
   var
     endexceptlabel: tasmlabel;
     endexceptlabel: tasmlabel;
@@ -169,6 +171,7 @@ constructor tx64tryfinallynode.create(l, r: TNode);
       end;
       end;
   end;
   end;
 
 
+
 constructor tx64tryfinallynode.create_implicit(l, r: TNode);
 constructor tx64tryfinallynode.create_implicit(l, r: TNode);
   begin
   begin
     inherited create_implicit(l, r);
     inherited create_implicit(l, r);
@@ -185,6 +188,33 @@ constructor tx64tryfinallynode.create_implicit(l, r: TNode);
       end;
       end;
   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;
 function tx64tryfinallynode.simplify(forinline: boolean): tnode;
   begin
   begin
     result:=inherited simplify(forinline);
     result:=inherited simplify(forinline);
@@ -192,22 +222,27 @@ function tx64tryfinallynode.simplify(forinline: boolean): tnode;
       exit;
       exit;
     if (result=nil) then
     if (result=nil) then
       begin
       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
           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 }
             { don't leave dangling pointer }
             tcgprocinfo(current_procinfo).final_asmnode:=nil;
             tcgprocinfo(current_procinfo).final_asmnode:=nil;
           end;
           end;
       end;
       end;
   end;
   end;
 
 
+
 procedure emit_nop;
 procedure emit_nop;
   var
   var
     dummy: TAsmLabel;
     dummy: TAsmLabel;
@@ -219,6 +254,7 @@ procedure emit_nop;
     current_asmdata.CurrAsmList.concat(Taicpu.op_none(A_NOP,S_NO));
     current_asmdata.CurrAsmList.concat(Taicpu.op_none(A_NOP,S_NO));
   end;
   end;
 
 
+
 procedure tx64tryfinallynode.pass_generate_code;
 procedure tx64tryfinallynode.pass_generate_code;
   var
   var
     trylabel,
     trylabel,

+ 13 - 0
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.

+ 12 - 0
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.