소스 검색

* fixed loading the nested framepointer when calling another nested
routine at the same or a higher nesting level in case the current
nested routine's framepointer was not part of the nestedfpstruct
(because it doesn't have nested routines itself, or because those
don't access any data in parent routines) on targets with explicit
parentfpstruct management (JVM) + adapted test

git-svn-id: branches/jvmbackend@19164 -

Jonas Maebe 14 년 전
부모
커밋
39adb3dfae
2개의 변경된 파일43개의 추가작업 그리고 10개의 파일을 삭제
  1. 18 10
      compiler/ncgnstmm.pas
  2. 25 0
      tests/test/jvm/tnestproc.pp

+ 18 - 10
compiler/ncgnstmm.pas

@@ -87,24 +87,33 @@ implementation
       var
       var
         fsym        : tfieldvarsym;
         fsym        : tfieldvarsym;
         hsym        : tparavarsym;
         hsym        : tparavarsym;
-        currpi,
-        nextpi      : tprocinfo;
+        currpi      : tprocinfo;
+        useparentfppara :  boolean;
       begin
       begin
         result:=nil;
         result:=nil;
-        if not assigned(current_procinfo.procdef.parentfpstruct) then
+        { if the current routine does not call a nested routine, or if that
+          nested routine does nothing for which it needs the nestedfp pointer
+          of the current routine (and hence it has not been moved into the
+          nestedfp struct), get the original nestedfp parameter }
+        useparentfppara:=not assigned(current_procinfo.procdef.parentfpstruct);
+        hsym:=tparavarsym(current_procinfo.procdef.parast.Find('parentfp'));
+        if current_procinfo.procdef.parast.symtablelevel>parentpd.parast.symtablelevel then
+          useparentfppara:=
+            useparentfppara or
+            (find_sym_in_parentfpstruct(current_procinfo.procdef,hsym)=nil);
+        if useparentfppara then
           begin
           begin
-            hsym:=tparavarsym(current_procinfo.procdef.parast.Find('parentfp'));
             result:=cloadnode.create(hsym,hsym.owner);
             result:=cloadnode.create(hsym,hsym.owner);
+            currpi:=current_procinfo.parent;
           end
           end
         else
         else
           begin
           begin
             result:=caddrnode.create_internal(cloadnode.create(current_procinfo.procdef.parentfpstruct,current_procinfo.procdef.parentfpstruct.owner));
             result:=caddrnode.create_internal(cloadnode.create(current_procinfo.procdef.parentfpstruct,current_procinfo.procdef.parentfpstruct.owner));
             include(result.flags,nf_typedaddr);
             include(result.flags,nf_typedaddr);
+            currpi:=current_procinfo;
           end;
           end;
-        { mark all parent parentfp parameters for inclusion in the struct that
-          holds all locals accessed from nested routines }
-        currpi:=current_procinfo.parent;
-        nextpi:=currpi.parent;
+        { follow the chain of parentfpstructs until we arrive at the one we
+          need }
         while (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
         while (currpi.procdef.parast.symtablelevel>parentpd.parast.symtablelevel) do
           begin
           begin
             hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
             hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
@@ -112,8 +121,7 @@ implementation
             if not assigned(fsym) then
             if not assigned(fsym) then
               internalerror(2011060405);
               internalerror(2011060405);
             result:=csubscriptnode.create(fsym,cderefnode.create(result));
             result:=csubscriptnode.create(fsym,cderefnode.create(result));
-            currpi:=nextpi;
-            nextpi:=nextpi.parent;
+            currpi:=currpi.parent;
           end;
           end;
       end;
       end;
 
 

+ 25 - 0
tests/test/jvm/tnestproc.pp

@@ -9,9 +9,16 @@ procedure outer(var para: byte);
   const xxx: longint = 5;
   const xxx: longint = 5;
   var
   var
     a: longint;
     a: longint;
+    called: boolean;
 
 
   procedure inner;
   procedure inner;
     begin
     begin
+      if not called then
+        begin
+          called:=true;
+          inner;
+          exit;
+        end;
       if a<>1 then
       if a<>1 then
         raise JLException.Create('a1');
         raise JLException.Create('a1');
       if para<>2 then
       if para<>2 then
@@ -20,8 +27,26 @@ procedure outer(var para: byte);
       para:=3;
       para:=3;
     end;
     end;
 
 
+
+  procedure inner2;
+    var
+      b: longint;
+  
+    procedure doubleinner;
+      begin
+        b:=3;
+      end;
+      
+    begin
+      doubleinner;
+      if b<>3 then
+        raise JLException.Create('b');
+      inner;
+    end;
+
   begin
   begin
     a:=1;
     a:=1;
+    called:=false;
     inner;
     inner;
     if a<>2 then
     if a<>2 then
       raise JLException.Create('a2');
       raise JLException.Create('a2');