Browse Source

* 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 years ago
parent
commit
39adb3dfae
2 changed files with 43 additions and 10 deletions
  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
         fsym        : tfieldvarsym;
         hsym        : tparavarsym;
-        currpi,
-        nextpi      : tprocinfo;
+        currpi      : tprocinfo;
+        useparentfppara :  boolean;
       begin
         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
-            hsym:=tparavarsym(current_procinfo.procdef.parast.Find('parentfp'));
             result:=cloadnode.create(hsym,hsym.owner);
+            currpi:=current_procinfo.parent;
           end
         else
           begin
             result:=caddrnode.create_internal(cloadnode.create(current_procinfo.procdef.parentfpstruct,current_procinfo.procdef.parentfpstruct.owner));
             include(result.flags,nf_typedaddr);
+            currpi:=current_procinfo;
           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
           begin
             hsym:=tparavarsym(currpi.procdef.parast.Find('parentfp'));
@@ -112,8 +121,7 @@ implementation
             if not assigned(fsym) then
               internalerror(2011060405);
             result:=csubscriptnode.create(fsym,cderefnode.create(result));
-            currpi:=nextpi;
-            nextpi:=nextpi.parent;
+            currpi:=currpi.parent;
           end;
       end;
 

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

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