瀏覽代碼

* keep track of static symbols that a global function references, as those must now be exported from a dynamic package as well if the function can potentially be inlined

git-svn-id: trunk@43544 -
svenbarth 5 年之前
父節點
當前提交
0a915e883e

+ 2 - 2
compiler/htypechk.pas

@@ -857,7 +857,7 @@ implementation
             exit;
           end;
 
-        addsymref(operpd.procsym);
+        addsymref(operpd.procsym,operpd);
 
         { the nil as symtable signs firstcalln that this is
           an overloaded operator }
@@ -1052,7 +1052,7 @@ implementation
             exit;
           end;
 
-        addsymref(operpd.procsym);
+        addsymref(operpd.procsym,operpd);
 
         { the nil as symtable signs firstcalln that this is
           an overloaded operator }

+ 1 - 1
compiler/ncal.pas

@@ -3787,7 +3787,7 @@ implementation
             { add reference to corresponding procsym; may not be the one
               originally found/passed to the constructor because of overloads }
             if procdefinition.typ = procdef then
-              addsymref(tprocdef(procdefinition).procsym);
+              addsymref(tprocdef(procdefinition).procsym,procdefinition);
 
             { add needed default parameters }
             if (paralength<procdefinition.maxparacount) then

+ 1 - 1
compiler/ncnv.pas

@@ -2513,7 +2513,7 @@ implementation
               te_convert_operator :
                 begin
                   include(current_procinfo.flags,pi_do_call);
-                  addsymref(aprocdef.procsym);
+                  addsymref(aprocdef.procsym,aprocdef);
                   hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[],nil);
                   { tell explicitly which def we must use !! (PM) }
                   tcallnode(hp).procdefinition:=aprocdef;

+ 1 - 1
compiler/nflw.pas

@@ -793,7 +793,7 @@ implementation
             enum_get_params:=ccallparanode.create(expr.getcopy,nil);
             enum_get:=ccallnode.create(enum_get_params, tprocsym(enumerator_get.procsym), nil, nil, [],nil);
             tcallnode(enum_get).procdefinition:=enumerator_get;
-            addsymref(enumerator_get.procsym);
+            addsymref(enumerator_get.procsym,enumerator_get);
           end
         else
           enum_get:=ccallnode.create(nil, tprocsym(enumerator_get.procsym), enumerator_get.owner, expr.getcopy, [],nil);

+ 5 - 2
compiler/pkgutil.pas

@@ -88,7 +88,10 @@ implementation
                 (symtable.symtabletype in [globalsymtable,recordsymtable,objectsymtable]) or
                 (
                   (symtable.symtabletype=staticsymtable) and
-                  ([po_public,po_has_public_name]*pd.procoptions<>[])
+                  (
+                    ([po_public,po_has_public_name]*pd.procoptions<>[]) or
+                    (df_has_global_ref in pd.defoptions)
+                  )
                 )
               ) then
             begin
@@ -217,7 +220,7 @@ implementation
           end;
         staticvarsym:
           begin
-            if publiconly and not (vo_is_public in tstaticvarsym(sym).varoptions) then
+            if publiconly and ([vo_is_public,vo_has_global_ref]*tstaticvarsym(sym).varoptions=[]) then
               exit;
             varexport(tsym(sym).mangledname);
           end;

+ 61 - 1
compiler/procinfo.pas

@@ -140,6 +140,11 @@ unit procinfo;
             need to be checked explicitly like on RISC-V or certain ARM architectures }
           FPUExceptionCheckNeeded : Boolean;
 
+          { local symbols and defs referenced by global functions; these need
+            to be exported in case the function gets inlined }
+          localrefsyms : tfpobjectlist;
+          localrefdefs : tfpobjectlist;
+
           constructor create(aparent:tprocinfo);virtual;
           destructor destroy;override;
 
@@ -170,6 +175,11 @@ unit procinfo;
           function has_nestedprocs: boolean;
           function get_normal_proc: tprocinfo;
 
+          procedure add_local_ref_sym(sym:tsym);
+          procedure export_local_ref_syms;
+          procedure add_local_ref_def(def:tdef);
+          procedure export_local_ref_defs;
+
           function create_for_outlining(const basesymname: string; astruct: tabstractrecorddef; potype: tproctypeoption; resultdef: tdef; entrynodeinfo: tnode): tprocinfo;
 
           { Add to parent's list of nested procedures even if parent is a 'main' procedure }
@@ -203,7 +213,7 @@ unit procinfo;
 implementation
 
     uses
-      globals,cutils,systems,
+      globals,cutils,systems,verbose,
       procdefutil;
 
 {****************************************************************************
@@ -244,6 +254,8 @@ implementation
          nestedprocs.free;
          aktproccode.free;
          aktlocaldata.free;
+         localrefsyms.free;
+         localrefdefs.free;
       end;
 
     procedure tprocinfo.destroy_tree;
@@ -288,6 +300,54 @@ implementation
           result:=result.parent;
       end;
 
+    procedure tprocinfo.add_local_ref_sym(sym:tsym);
+      begin
+        if not assigned(localrefsyms) then
+          localrefsyms:=tfpobjectlist.create(false);
+        if localrefsyms.indexof(sym)<0 then
+          localrefsyms.add(sym);
+      end;
+
+    procedure tprocinfo.export_local_ref_syms;
+      var
+        i : longint;
+        sym : tsym;
+      begin
+        if not assigned(localrefsyms) then
+          exit;
+        for i:=0 to localrefsyms.count-1 do
+          begin
+            sym:=tsym(localrefsyms[i]);
+            if sym.typ<>staticvarsym then
+              internalerror(2019110901);
+            include(tstaticvarsym(sym).varoptions,vo_has_global_ref);
+          end;
+      end;
+
+    procedure tprocinfo.add_local_ref_def(def:tdef);
+      begin
+        if not assigned(localrefdefs) then
+          localrefdefs:=tfpobjectlist.create(false);
+        if localrefdefs.indexof(def)<0 then
+          localrefdefs.add(def);
+      end;
+
+    procedure tprocinfo.export_local_ref_defs;
+      var
+        i : longint;
+        def : tdef;
+      begin
+        if not assigned(localrefdefs) then
+          exit;
+        for i:=0 to localrefdefs.count-1 do
+          begin
+            def:=tdef(localrefdefs[i]);
+            if def.typ<>symconst.procdef then
+              internalerror(2019111801);
+            include(tprocdef(def).defoptions,df_has_global_ref);
+          end;
+      end;
+
     function tprocinfo.create_for_outlining(const basesymname: string; astruct: tabstractrecorddef; potype: tproctypeoption; resultdef: tdef; entrynodeinfo: tnode): tprocinfo;
       begin
         result:=cprocinfo.create(self);

+ 2 - 0
compiler/psub.pas

@@ -1384,6 +1384,8 @@ implementation
         if procdef.inlininginfo^.code.nodetype=blockn then
           include(procdef.inlininginfo^.code.flags,nf_block_with_exit);
         procdef.has_inlininginfo:=true;
+        export_local_ref_syms;
+        export_local_ref_defs;
        end;
 
     procedure searchthreadvar(p: TObject; arg: pointer);

+ 6 - 2
compiler/symconst.pas

@@ -232,7 +232,9 @@ type
       because we have to access this information in the symtable unit }
     df_llvm_no_struct_packing,
     { internal def that's not for any export }
-    df_internal
+    df_internal,
+    { the local def is referenced from a public function }
+    df_has_global_ref
   );
   tdefoptions=set of tdefoption;
 
@@ -607,7 +609,9 @@ type
       sections }
     vo_is_default_var,
     { i8086 'external far' (can only be used in combination with vo_is_external) }
-    vo_is_far
+    vo_is_far,
+    { a static symbol that is referenced from a global function }
+    vo_has_global_ref
   );
   tvaroptions=set of tvaroption;
 

+ 44 - 4
compiler/symtable.pas

@@ -334,7 +334,8 @@ interface
     procedure write_system_parameter_lists(const name:string);
 
 {*** Search ***}
-    procedure addsymref(sym:tsym);
+    procedure addsymref(sym:tsym);inline;
+    procedure addsymref(sym:tsym;def:tdef);
     function  is_owned_by(nesteddef,ownerdef:tdef):boolean;
     function  sym_is_owned_by(childsym:tsym;symtable:tsymtable):boolean;
     function  defs_belong_to_same_generic(def1,def2:tdef):boolean;
@@ -474,7 +475,7 @@ implementation
 
     uses
       { global }
-      verbose,globals,
+      verbose,globals,systems,
       { symtable }
       symutil,defutil,defcmp,objcdef,
       { module }
@@ -3029,9 +3030,9 @@ implementation
                                   Search
 *****************************************************************************}
 
-     procedure addsymref(sym:tsym);
+     procedure addsymref(sym:tsym;def:tdef);
        var
-         owner: tsymtable;
+         owner,procowner : tsymtable;
        begin
          { for symbols used in preprocessor expressions, we don't want to
            increase references count (for smaller final binaries) }
@@ -3063,8 +3064,47 @@ implementation
                  { symbol is imported from another unit }
                  current_module.addimportedsym(sym);
              end;
+         { static symbols that are used in public functions must be exported
+           for packages as well }
+         if ([tf_supports_packages,tf_supports_hidden_symbols]<=target_info.flags) and
+             (owner.symtabletype=staticsymtable) and
+             assigned(current_procinfo) and
+             (
+               (
+                 (sym.typ=staticvarsym) and
+                 ([vo_is_public,vo_has_global_ref]*tstaticvarsym(sym).varoptions=[])
+               ) or (
+                 (sym.typ=localvarsym) and
+                 assigned(tlocalvarsym(sym).defaultconstsym) and
+                 ([vo_is_public,vo_has_global_ref]*tstaticvarsym(tlocalvarsym(sym).defaultconstsym).varoptions=[])
+               ) or (
+                 (sym.typ=procsym) and
+                 assigned(def) and
+                 (def.typ=procdef) and
+                 not (df_has_global_ref in def.defoptions) and
+                 not (po_public in tprocdef(def).procoptions)
+               )
+             ) then
+           begin
+             procowner:=current_procinfo.procdef.owner;
+             while procowner.symtabletype in [objectsymtable,recordsymtable] do
+               procowner:=tdef(procowner.defowner).owner;
+             if procowner.symtabletype=globalsymtable then
+               begin
+                 if sym.typ=procsym then
+                   current_procinfo.add_local_ref_def(def)
+                 else if sym.typ=staticvarsym then
+                   current_procinfo.add_local_ref_sym(sym)
+                 else
+                   current_procinfo.add_local_ref_sym(tlocalvarsym(sym).defaultconstsym);
+               end;
+           end;
        end;
 
+     procedure addsymref(sym:tsym);
+       begin
+         addsymref(sym,nil);
+       end;
 
     function is_owned_by(nesteddef,ownerdef:tdef):boolean;
       begin

+ 4 - 2
compiler/utils/ppuutils/ppudump.pp

@@ -2729,7 +2729,8 @@ const
      { this should never happen for defs stored to a ppu file }
      (mask:df_not_registered_no_free;  str:'Unregistered/No free (invalid)'),
      (mask:df_llvm_no_struct_packing;  str:'LLVM unpacked struct'),
-     (mask:df_internal;       str:'Internal')
+     (mask:df_internal;       str:'Internal'),
+     (mask:df_has_global_ref; str:'Has Global Ref')
   );
   defstate : array[1..ord(high(tdefstate))] of tdefstateinfo=(
      (mask:ds_vmt_written;           str:'VMT Written'),
@@ -3068,7 +3069,8 @@ const
      (mask:vo_has_section;     str:'HasSection'),
      (mask:vo_force_finalize;  str:'ForceFinalize'),
      (mask:vo_is_default_var;  str:'DefaultIntrinsicVar'),
-     (mask:vo_is_far;          str:'IsFar')
+     (mask:vo_is_far;          str:'IsFar'),
+     (mask:vo_has_global_ref;  str:'HasGlobalRef')
   );
 type
   tvaraccessdesc=record