summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/htypechk.pas4
-rw-r--r--compiler/ncal.pas2
-rw-r--r--compiler/ncnv.pas2
-rw-r--r--compiler/nflw.pas2
-rw-r--r--compiler/pkgutil.pas7
-rw-r--r--compiler/procinfo.pas62
-rw-r--r--compiler/psub.pas2
-rw-r--r--compiler/symconst.pas8
-rw-r--r--compiler/symtable.pas48
-rw-r--r--compiler/utils/ppuutils/ppudump.pp6
10 files changed, 127 insertions, 16 deletions
diff --git a/compiler/htypechk.pas b/compiler/htypechk.pas
index 2a9f378f75..5bb207cc89 100644
--- a/compiler/htypechk.pas
+++ b/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 }
diff --git a/compiler/ncal.pas b/compiler/ncal.pas
index a85e12c3cf..27d863c8a2 100644
--- a/compiler/ncal.pas
+++ b/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
diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas
index 9a7e658a50..4e32164e82 100644
--- a/compiler/ncnv.pas
+++ b/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;
diff --git a/compiler/nflw.pas b/compiler/nflw.pas
index 9a00608288..8a5a3c0081 100644
--- a/compiler/nflw.pas
+++ b/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);
diff --git a/compiler/pkgutil.pas b/compiler/pkgutil.pas
index b61ddd55e0..7f17e51c16 100644
--- a/compiler/pkgutil.pas
+++ b/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;
diff --git a/compiler/procinfo.pas b/compiler/procinfo.pas
index 02e073a43f..7279dd05c7 100644
--- a/compiler/procinfo.pas
+++ b/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);
diff --git a/compiler/psub.pas b/compiler/psub.pas
index 4cebaff3ac..641e35df98 100644
--- a/compiler/psub.pas
+++ b/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);
diff --git a/compiler/symconst.pas b/compiler/symconst.pas
index 07e1659a07..e56ba0e3c9 100644
--- a/compiler/symconst.pas
+++ b/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;
diff --git a/compiler/symtable.pas b/compiler/symtable.pas
index 9c58e36a40..1ce4a69890 100644
--- a/compiler/symtable.pas
+++ b/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
diff --git a/compiler/utils/ppuutils/ppudump.pp b/compiler/utils/ppuutils/ppudump.pp
index 6940791192..50005c68a9 100644
--- a/compiler/utils/ppuutils/ppudump.pp
+++ b/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