* 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 -
This commit is contained in:
svenbarth 2019-11-21 21:44:53 +00:00
parent 2e259ee3cc
commit 0a915e883e
10 changed files with 127 additions and 16 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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