diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/htypechk.pas | 4 | ||||
-rw-r--r-- | compiler/ncal.pas | 2 | ||||
-rw-r--r-- | compiler/ncnv.pas | 2 | ||||
-rw-r--r-- | compiler/nflw.pas | 2 | ||||
-rw-r--r-- | compiler/pkgutil.pas | 7 | ||||
-rw-r--r-- | compiler/procinfo.pas | 62 | ||||
-rw-r--r-- | compiler/psub.pas | 2 | ||||
-rw-r--r-- | compiler/symconst.pas | 8 | ||||
-rw-r--r-- | compiler/symtable.pas | 48 | ||||
-rw-r--r-- | compiler/utils/ppuutils/ppudump.pp | 6 |
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 |