mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 00:09:32 +02:00
* 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:
parent
2e259ee3cc
commit
0a915e883e
@ -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 }
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user