Browse Source

* don't store reusable defs based on other defs from localsymtables into the
static/globalsymtable. The static/global symtable is stored to the PPU
while the localsymtables are not, which means we get dangling references
when reloading such defs from the ppu afterwards

git-svn-id: trunk@31149 -

Jonas Maebe 10 years ago
parent
commit
b21610050f
3 changed files with 45 additions and 21 deletions
  1. 19 16
      compiler/symdef.pas
  2. 21 0
      compiler/symtype.pas
  3. 5 5
      compiler/x86/symx86.pas

+ 19 - 16
compiler/symdef.pas

@@ -3120,6 +3120,7 @@ implementation
       var
         res: PHashSetItem;
         oldsymtablestack: tsymtablestack;
+        savesymtab: tsymtable;
       begin
         if not assigned(current_module) then
           internalerror(2011071101);
@@ -3127,16 +3128,16 @@ implementation
         if not assigned(res^.Data) then
           begin
             { since these pointerdefs can be reused anywhere in the current
-              unit, add them to the global/staticsymtable }
+              unit, add them to the global/staticsymtable (or local symtable
+              if they're a local def, because otherwise they'll be saved
+              to the ppu referencing a local symtable entry that doesn't
+              exist in the ppu) }
             oldsymtablestack:=symtablestack;
             { do not simply push/pop current_module.localsymtable, because
               that can have side-effects (e.g., it removes helpers) }
             symtablestack:=nil;
             res^.Data:=cpointerdef.create(def);
-            if assigned(current_module.localsymtable) then
-              current_module.localsymtable.insertdef(tdef(res^.Data))
-            else
-              current_module.globalsymtable.insertdef(tdef(res^.Data));
+            def.getreusablesymtab.insertdef(tdef(res^.Data));
             symtablestack:=oldsymtablestack;
           end;
         result:=tpointerdef(res^.Data);
@@ -3436,16 +3437,18 @@ implementation
         res:=current_module.arraydefs.FindOrAdd(@arrdesc,sizeof(arrdesc));
         if not assigned(res^.Data) then
           begin
-            { since these arraydef can be reused anywhere in the current
-              unit, add them to the global/staticsymtable }
+            { since these pointerdefs can be reused anywhere in the current
+              unit, add them to the global/staticsymtable (or local symtable
+              if they're a local def, because otherwise they'll be saved
+              to the ppu referencing a local symtable entry that doesn't
+              exist in the ppu) }
             oldsymtablestack:=symtablestack;
+            { do not simply push/pop current_module.localsymtable, because
+              that can have side-effects (e.g., it removes helpers) }
             symtablestack:=nil;
             res^.Data:=carraydef.create(0,elems-1,ptrsinttype);
             tarraydef(res^.Data).elementdef:=def;
-            if assigned(current_module.localsymtable) then
-              current_module.localsymtable.insertdef(tdef(res^.Data))
-            else
-              current_module.globalsymtable.insertdef(tdef(res^.Data));
+            def.getreusablesymtab.insertdef(tdef(res^.Data));
             symtablestack:=oldsymtablestack;
           end;
         result:=tarraydef(res^.Data);
@@ -5910,16 +5913,16 @@ implementation
         if not assigned(res^.Data) then
           begin
             { since these pointerdefs can be reused anywhere in the current
-              unit, add them to the global/staticsymtable }
+              unit, add them to the global/staticsymtable (or local symtable
+              if they're a local def, because otherwise they'll be saved
+              to the ppu referencing a local symtable entry that doesn't
+              exist in the ppu) }
             oldsymtablestack:=symtablestack;
             { do not simply push/pop current_module.localsymtable, because
               that can have side-effects (e.g., it removes helpers) }
             symtablestack:=nil;
             res^.Data:=def.getcopyas(procvardef,pc_address_only);
-            if assigned(current_module.localsymtable) then
-              current_module.localsymtable.insertdef(tdef(res^.Data))
-            else
-              current_module.globalsymtable.insertdef(tdef(res^.Data));
+            def.getreusablesymtab.insertdef(tdef(res^.Data));
             symtablestack:=oldsymtablestack;
           end;
         result:=tprocvardef(res^.Data);

+ 21 - 0
compiler/symtype.pas

@@ -88,6 +88,7 @@ interface
          function  needs_inittable:boolean;virtual;abstract;
          function  needs_separate_initrtti:boolean;virtual;abstract;
          procedure ChangeOwner(st:TSymtable);
+         function getreusablesymtab: tsymtable;
          procedure register_created_object_type;virtual;
          function  get_top_level_symtable: tsymtable;
       end;
@@ -353,6 +354,26 @@ implementation
       end;
 
 
+    function tdef.getreusablesymtab: tsymtable;
+      var
+        origowner: TSymtable;
+      begin
+        { if the original def was in a localsymtable, don't create a
+          reusable copy in the unit's staticsymtable since the localsymtable
+          won't be saved to the ppu and as a result we can get unreachable
+          defs when reloading the derived ones from the ppu }
+        origowner:=owner;
+        while not(origowner.symtabletype in [localsymtable,staticsymtable,globalsymtable]) do
+          origowner:=origowner.defowner.owner;
+        if origowner.symtabletype=localsymtable then
+          result:=origowner
+        else if assigned(current_module.localsymtable) then
+          result:=current_module.localsymtable
+        else
+          result:=current_module.globalsymtable;
+      end;
+
+
     procedure tdef.register_created_object_type;
       begin
       end;

+ 5 - 5
compiler/x86/symx86.pas

@@ -103,16 +103,16 @@ implementation
       if not assigned(res^.Data) then
         begin
           { since these pointerdefs can be reused anywhere in the current
-            unit, add them to the global/staticsymtable }
+            unit, add them to the global/staticsymtable (or local symtable
+            if they're a local def, because otherwise they'll be saved
+            to the ppu referencing a local symtable entry that doesn't
+            exist in the ppu) }
           oldsymtablestack:=symtablestack;
           { do not simply push/pop current_module.localsymtable, because
             that can have side-effects (e.g., it removes helpers) }
           symtablestack:=nil;
           res^.Data:=tx86pointerdefclass(cpointerdef).createx86(def,x86typ);
-          if assigned(current_module.localsymtable) then
-            current_module.localsymtable.insertdef(tdef(res^.Data))
-          else
-            current_module.globalsymtable.insertdef(tdef(res^.Data));
+          def.getreusablesymtab.insertdef(tdef(res^.Data));
           symtablestack:=oldsymtablestack;
         end;
       result:=tpointerdef(res^.Data);