Преглед на файлове

* 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 -

Jonas Maebe преди 18 години
родител
ревизия
49a2084ea0
променени са 7 файла, в които са добавени 96 реда и са изтрити 5 реда
  1. 1 0
      .gitattributes
  2. 14 0
      compiler/nbas.pas
  3. 7 3
      compiler/ncal.pas
  4. 7 0
      compiler/ncgbas.pas
  5. 3 1
      compiler/ncgutil.pas
  6. 1 1
      compiler/ppu.pas
  7. 63 0
      tests/test/tinline8.pp

+ 1 - 0
.gitattributes

@@ -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

+ 14 - 0
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;

+ 7 - 3
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;

+ 7 - 0
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;
 

+ 3 - 1
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 }

+ 1 - 1
compiler/ppu.pas

@@ -43,7 +43,7 @@ type
 {$endif Test_Double_checksum}
 
 const
-  CurrentPPUVersion=81;
+  CurrentPPUVersion=82;
 
 { buffer sizes }
   maxentrysize = 1024;

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