From 2cea723a0de6eeb14ae7bf6e2db93f2155ff821e Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sun, 25 Oct 2015 19:22:00 +0000 Subject: [PATCH] * only write the parts of the unit localsymtables that are actually needed: the defs and syms (recursively) referred by inline routines and by the WPO info o defs and syms are no longer added immediately to the module's deflist/ symlist, even if they are created as "registered". Instead, "doregister=true" simply means "add it to the symbol table at the top of the symtable stack" o normally only when a sym/def is deref'ed, it gets added to the module symlist/deflist and defid/symid gets a (unique) value o in cases where we use(d) the defid to construct unique names within the current module, you now have to call call the tdef.new unique_id_str() method. If the def was not yet registered, we will reserve room for it in the deflist (to get a unique id), but the defid gets set to a negative value computed from its position in the deflist. Should it have to be written to the ppu file later on, the defid will be modified to the actual position in the deflist. For both values, new unique_id_str() will return the same result so that references to this def before and after actual registrations are the same (needed for the JVM backend, but also a good principle in general) Overall: don't directly use symid/defid anymore to get unique identifiers, but use tdef.new unique_id_str() instead (if necessary, a similar routine for tsym can be added) The result is the ppu file size gets reduced significantly after its big increase as a result of the high level typed constant builder (which creates a lot of defs). The result is even more efficient than before, as other unneeded defs/syms from the localsymtables don't get saved/restored anymore either. git-svn-id: trunk@32153 - --- compiler/blockutl.pas | 8 +-- compiler/fppu.pas | 24 ++++---- compiler/jvm/jvmdef.pas | 4 +- compiler/jvm/pjvm.pas | 12 ++-- compiler/jvm/symcpu.pas | 8 +-- compiler/pexpr.pas | 2 +- compiler/pgenutil.pas | 2 +- compiler/symconst.pas | 8 +-- compiler/symcreat.pas | 4 +- compiler/symdef.pas | 63 +++++++++++--------- compiler/symsym.pas | 24 +++++--- compiler/symtable.pas | 124 ++++++++++++++++++++++++++++++++++------ compiler/symtype.pas | 75 +++++++++++++++++++++++- 13 files changed, 269 insertions(+), 89 deletions(-) diff --git a/compiler/blockutl.pas b/compiler/blockutl.pas index 89bdeab0c3..94aede1a2a 100644 --- a/compiler/blockutl.pas +++ b/compiler/blockutl.pas @@ -160,9 +160,9 @@ implementation { must be a valid Pascal identifier, because we will reference it when constructing the block initialiser } { we don't have to include the moduleid in this mangledname, because - the invokepd is a local procedure in the current unit -> defid by - itself is unique } - name:='__FPC_BLOCK_DESCRIPTOR_SIMPLE_'+tostr(invokepd.defid); + the invokepd is a local procedure in the current unit -> unique_id_str + by itself is unique } + name:='__FPC_BLOCK_DESCRIPTOR_SIMPLE_'+invokepd.unique_id_str; { already exists -> return } if searchsym(name,srsym,srsymtable) then begin @@ -196,7 +196,7 @@ implementation begin { the copy() is to ensure we don't overflow the maximum identifier length; the combination of owner.moduleid and defid will make the name unique } - wrappername:='__FPC_BLOCK_INVOKE_'+upper(copy(orgpd.procsym.realname,1,60))+'_'+tostr(orgpd.owner.moduleid)+'_'+tostr(orgpd.defid); + wrappername:='__FPC_BLOCK_INVOKE_'+upper(copy(orgpd.procsym.realname,1,60))+'_'+tostr(orgpd.owner.moduleid)+'_'+orgpd.unique_id_str; { already an invoke wrapper for this procsym -> reuse } if searchsym(wrappername,srsym,srsymtable) then begin diff --git a/compiler/fppu.pas b/compiler/fppu.pas index f0dad5d5e2..1074a1ad1d 100644 --- a/compiler/fppu.pas +++ b/compiler/fppu.pas @@ -1197,13 +1197,10 @@ var position in derefdata is not necessarily at the end } derefdata.seek(derefdata.size); tstoredsymtable(globalsymtable).buildderefimpl; - if (flags and uf_local_symtable)<>0 then - begin - tstoredsymtable(localsymtable).buildderef; - tstoredsymtable(localsymtable).buildderefimpl; - end; tunitwpoinfo(wpoinfo).buildderef; tunitwpoinfo(wpoinfo).buildderefimpl; + if (flags and uf_local_symtable)<>0 then + tstoredsymtable(localsymtable).buildderef_registered; writederefmap; writederefdata; @@ -1477,9 +1474,12 @@ var end; { we can now derefence all pointers to the implementation parts } - tstoredsymtable(globalsymtable).derefimpl; + tstoredsymtable(globalsymtable).derefimpl(false); + { we've just loaded the localsymtable from the ppu file, so everything + in it was registered by definition (otherwise it wouldn't have been in + there) } if assigned(localsymtable) then - tstoredsymtable(localsymtable).derefimpl; + tstoredsymtable(localsymtable).derefimpl(false); { read whole program optimisation-related information } wpoinfo:=tunitwpoinfo.ppuload(ppufile); @@ -1608,12 +1608,14 @@ var if interface_compiled then begin Message1(unit_u_reresolving_unit,modulename^); - tstoredsymtable(globalsymtable).deref; - tstoredsymtable(globalsymtable).derefimpl; + tstoredsymtable(globalsymtable).deref(false); + tstoredsymtable(globalsymtable).derefimpl(false); if assigned(localsymtable) then begin - tstoredsymtable(localsymtable).deref; - tstoredsymtable(localsymtable).derefimpl; + { we have only builderef(impl)'d the registered symbols of + the localsymtable -> also only deref those again } + tstoredsymtable(localsymtable).deref(true); + tstoredsymtable(localsymtable).derefimpl(true); end; if assigned(wpoinfo) then begin diff --git a/compiler/jvm/jvmdef.pas b/compiler/jvm/jvmdef.pas index 7a028a8cf4..0c30fcf8cf 100644 --- a/compiler/jvm/jvmdef.pas +++ b/compiler/jvm/jvmdef.pas @@ -930,8 +930,8 @@ implementation begin if tdef(container.defowner).typ<>procdef then internalerror(2011040303); - { defid is added to prevent problem with overloads } - result:=tprocdef(container.defowner).procsym.realname+'$$'+tostr(tprocdef(container.defowner).defid)+'$'+result; + { unique_id_str is added to prevent problem with overloads } + result:=tprocdef(container.defowner).procsym.realname+'$$'+tprocdef(container.defowner).unique_id_str+'$'+result; container:=container.defowner.owner; end; end; diff --git a/compiler/jvm/pjvm.pas b/compiler/jvm/pjvm.pas index 5ee8cd8fc5..4880c6585b 100644 --- a/compiler/jvm/pjvm.pas +++ b/compiler/jvm/pjvm.pas @@ -297,7 +297,7 @@ implementation { create new class (different internal name than enum to prevent name clash; at unit level because we don't want its methods to be nested inside a function in case its a local type) } - enumclass:=cobjectdef.create(odt_javaclass,'$'+current_module.realmodulename^+'$'+name+'$InternEnum$'+tostr(def.defid),java_jlenum,true); + enumclass:=cobjectdef.create(odt_javaclass,'$'+current_module.realmodulename^+'$'+name+'$InternEnum$'+def.unique_id_str,java_jlenum,true); tcpuenumdef(def).classdef:=enumclass; include(enumclass.objectoptions,oo_is_enum_class); include(enumclass.objectoptions,oo_is_sealed); @@ -482,7 +482,7 @@ implementation { create new class (different internal name than pvar to prevent name clash; at unit level because we don't want its methods to be nested inside a function in case its a local type) } - pvclass:=cobjectdef.create(odt_javaclass,'$'+current_module.realmodulename^+'$'+name+'$InternProcvar$'+tostr(def.defid),java_procvarbase,true); + pvclass:=cobjectdef.create(odt_javaclass,'$'+current_module.realmodulename^+'$'+name+'$InternProcvar$'+def.unique_id_str,java_procvarbase,true); tcpuprocvardef(def).classdef:=pvclass; include(pvclass.objectoptions,oo_is_sealed); if df_generic in def.defoptions then @@ -640,10 +640,10 @@ implementation wrapperpv.calcparas; { no use in creating a callback wrapper here, this procvar type isn't for public consumption } - jvm_create_procvar_class_intern('__fpc_virtualclassmethod_pv_t'+tostr(wrapperpd.defid),wrapperpv,true); + jvm_create_procvar_class_intern('__fpc_virtualclassmethod_pv_t'+wrapperpd.unique_id_str,wrapperpv,true); { create alias for the procvar type so we can use it in generated Pascal code } - typ:=ctypesym.create('__fpc_virtualclassmethod_pv_t'+tostr(wrapperpd.defid),wrapperpv,true); + typ:=ctypesym.create('__fpc_virtualclassmethod_pv_t'+wrapperpd.unique_id_str,wrapperpv,true); wrapperpv.classdef.typesym.visibility:=vis_strictprivate; symtablestack.top.insert(typ); symtablestack.pop(pd.owner); @@ -836,8 +836,8 @@ implementation visname:=visibilityName[vis]; replace(visname,' ','_'); { create a name that is unique amongst all units (start with '$unitname$$') and - unique in this unit (result.defid) } - finish_copied_procdef(result,'$'+current_module.realmodulename^+'$$'+tostr(result.defid)+pd.procsym.realname+'$'+visname,obj.symtable,obj); + unique in this unit (result.unique_id_str) } + finish_copied_procdef(result,'$'+current_module.realmodulename^+'$$'+result.unique_id_str+pd.procsym.realname+'$'+visname,obj.symtable,obj); { in case the referred method is from an external class } exclude(result.procoptions,po_external); { not virtual/override/abstract/... } diff --git a/compiler/jvm/symcpu.pas b/compiler/jvm/symcpu.pas index c3fbdd769a..a238b9a1e5 100644 --- a/compiler/jvm/symcpu.pas +++ b/compiler/jvm/symcpu.pas @@ -385,9 +385,9 @@ implementation { method of this objectdef } pd.struct:=obj; { can only construct the artificial accessorname now, because it requires - pd.defid } + pd.unique_id_str } if not explicitwrapper then - accessorname:='$'+obj.symtable.realname^+'$'+realname+'$'+accessorname+'$'+tostr(pd.defid); + accessorname:='$'+obj.symtable.realname^+'$'+realname+'$'+accessorname+'$'+pd.unique_id_str; end else begin @@ -397,9 +397,9 @@ implementation exclude(pd.procoptions,po_abstractmethod); exclude(pd.procoptions,po_overridingmethod); { can only construct the artificial accessorname now, because it requires - pd.defid } + pd.unique_id_str } if not explicitwrapper then - accessorname:='$'+obj.symtable.realname^+'$'+realname+'$'+accessorname+'$'+tostr(pd.defid); + accessorname:='$'+obj.symtable.realname^+'$'+realname+'$'+accessorname+'$'+pd.unique_id_str; finish_copied_procdef(pd,accessorname,obj.symtable,obj); sym:=pd.procsym; end; diff --git a/compiler/pexpr.pas b/compiler/pexpr.pas index 14277730a4..217a1ef154 100644 --- a/compiler/pexpr.pas +++ b/compiler/pexpr.pas @@ -2818,7 +2818,7 @@ implementation findwithsymtable then begin { create dummy symbol, it will be freed later on } - srsym:=tsym.create(undefinedsym,'$undefinedsym'); + srsym:=tstoredsym.create(undefinedsym,'$undefinedsym',false); srsymtable:=nil; end else diff --git a/compiler/pgenutil.pas b/compiler/pgenutil.pas index 331f36c5f6..25f0a35ea1 100644 --- a/compiler/pgenutil.pas +++ b/compiler/pgenutil.pas @@ -354,7 +354,7 @@ uses { special handling for specializations inside generic function declarations } if symtablestack.top.defowner.typ<>procdef then internalerror(2015080101); - str(symtablestack.top.defowner.defid,namepart); + namepart:=tdef(symtablestack.top.defowner).unique_id_str; namepart:='genproc'+namepart+'_'+tdef(symtablestack.top.defowner).fullownerhierarchyname+'_'+tprocdef(symtablestack.top.defowner).procsym.realname+'_'+typeparam.resultdef.typename; prettynamepart:=tdef(symtablestack.top.defowner).fullownerhierarchyname+tprocdef(symtablestack.top.defowner).procsym.prettyname; end diff --git a/compiler/symconst.pas b/compiler/symconst.pas index 5e41016c48..0c7e382efb 100644 --- a/compiler/symconst.pas +++ b/compiler/symconst.pas @@ -146,15 +146,15 @@ const class_helper_prefix = 'CH$'; { tsym.symid value in case the sym has not yet been registered } - symid_not_registered = -1; + symid_not_registered = -2; { tsym.symid value in case the sym has been registered, but not put in a symtable } - symid_registered_nost = -2; + symid_registered_nost = -1; { tdef.defid value in case the def has not yet been registered } - defid_not_registered = -1; + defid_not_registered = -2; { tdef.defid value in case the sym has been registered, but not put in a symtable } - defid_registered_nost = -2; + defid_registered_nost = -1; type { keep this in sync with TIntfFlag in rtl/objpas/typinfo.pp } diff --git a/compiler/symcreat.pas b/compiler/symcreat.pas index a0146e33ce..e59044b8e3 100644 --- a/compiler/symcreat.pas +++ b/compiler/symcreat.pas @@ -822,7 +822,7 @@ implementation callpd: tprocdef; begin callpd:=tprocdef(pd.skpara); - str:='var pv: __fpc_virtualclassmethod_pv_t'+tostr(pd.defid)+'; begin ' + str:='var pv: __fpc_virtualclassmethod_pv_t'+pd.unique_id_str+'; begin ' + 'pv:=@'+callpd.procsym.RealName+';'; if (pd.proctypeoption<>potype_constructor) and not is_void(pd.returndef) then @@ -1151,7 +1151,7 @@ implementation { create struct to hold local variables and parameters that are accessed from within nested routines (start with extra dollar to prevent the JVM from thinking this is a nested class in the unit) } - nestedvarsst:=trecordsymtable.create('$'+current_module.realmodulename^+'$$_fpc_nestedvars$'+tostr(pd.defid), + nestedvarsst:=trecordsymtable.create('$'+current_module.realmodulename^+'$$_fpc_nestedvars$'+pd.unique_id_str, current_settings.alignment.localalignmax,current_settings.alignment.localalignmin,current_settings.alignment.maxCrecordalign); nestedvarsdef:=crecorddef.create(nestedvarsst.name^,nestedvarsst); {$ifdef jvm} diff --git a/compiler/symdef.pas b/compiler/symdef.pas index 716e051cae..dd35497a19 100644 --- a/compiler/symdef.pas +++ b/compiler/symdef.pas @@ -68,8 +68,6 @@ interface procedure writeentry(ppufile: tcompilerppufile; ibnr: byte); protected typesymderef : tderef; - { whether this def is already registered in the unit's def list } - function registered : boolean; procedure ppuwrite_platform(ppufile:tcompilerppufile);virtual; procedure ppuload_platform(ppufile:tcompilerppufile);virtual; public @@ -121,8 +119,10 @@ interface { same as above for specializations } function is_specialization:boolean;inline; { registers this def in the unit's deflist; no-op if already registered } - procedure register_def; - property is_registered: boolean read registered; + procedure register_def; override; + { add the def to the top of the symtable stack if it's not yet owned + by another symtable } + procedure maybe_put_in_symtable_stack; private savesize : asizeuint; end; @@ -1222,7 +1222,7 @@ implementation typ: ttypesym; name: string; begin - name:=internaltypeprefixName[itp_threadvar_record]+tostr(def.defid); + name:=internaltypeprefixName[itp_threadvar_record]+def.unique_id_str; typ:=try_search_current_module_type(name); if assigned(typ) then begin @@ -1647,12 +1647,6 @@ implementation end; - function tstoreddef.registered: boolean; - begin - result:=defid<>defid_not_registered; - end; - - procedure tstoreddef.ppuwrite_platform(ppufile: tcompilerppufile); begin { by default: do nothing } @@ -1679,9 +1673,9 @@ implementation end of an type block } if (dt=forwarddef) then exit; - { register the definition if wanted } + { Register in symtable stack } if doregister then - register_def; + maybe_put_in_symtable_stack; end; @@ -1789,7 +1783,7 @@ implementation (owner.symtabletype in [staticsymtable,globalsymtable]) then result:=make_mangledname(prefix,typesym.owner,typesym.name) else - result:=make_mangledname(prefix,findunitsymtable(owner),'DEF'+tostr(DefId)) + result:=make_mangledname(prefix,findunitsymtable(owner),'def'+unique_id_str) end; @@ -1924,6 +1918,8 @@ implementation sym : tsym; symderef : pderef; begin + if not registered then + register_def; typesymderef.build(typesym); genericdefderef.build(genericdef); if assigned(genconstraintdata) then @@ -2137,21 +2133,32 @@ implementation procedure tstoreddef.register_def; - var - insertstack : psymtablestackitem; begin if registered then exit; { Register in current_module } if assigned(current_module) then begin - current_module.deflist.Add(self); - DefId:=current_module.deflist.Count-1; + if defidsymid_not_registered; + inherited; + if not registered then + register_sym; end; @@ -1303,6 +1303,14 @@ implementation inherited create(errorsym,''); end; + + procedure terrorsym.register_sym; + begin + { these should never be written to a ppu file, since they don't + derive from tstoredsym } + Internalerror(2015101801); + end; + {**************************************************************************** TPROPERTYSYM ****************************************************************************} @@ -1399,7 +1407,7 @@ implementation end else if ppo_hasparameters in propoptions then - tparasymtable(parast).deref + tparasymtable(parast).deref(false) end; diff --git a/compiler/symtable.pas b/compiler/symtable.pas index 71ba074ecc..ae00f547b3 100644 --- a/compiler/symtable.pas +++ b/compiler/symtable.pas @@ -58,10 +58,12 @@ interface { load/write } procedure ppuload(ppufile:tcompilerppufile);virtual; procedure ppuwrite(ppufile:tcompilerppufile);virtual; - procedure buildderef;virtual; - procedure buildderefimpl;virtual; - procedure deref;virtual; - procedure derefimpl;virtual; + procedure buildderef; + procedure buildderefimpl; + { buildderef but only for (recursively) used symbols/defs } + procedure buildderef_registered; + procedure deref(only_registered: boolean);virtual; + procedure derefimpl(only_registered: boolean);virtual; function checkduplicate(var hashedid:THashedIDString;sym:TSymEntry):boolean;override; procedure allsymbolsused; procedure allprivatesused; @@ -570,18 +572,24 @@ implementation procedure tstoredsymtable.writedefs(ppufile:tcompilerppufile); var + defcount, i : longint; def : tstoreddef; begin + defcount:=0; + for i:=0 to DefList.Count-1 do + if tstoreddef(DefList[i]).is_registered then + inc(defcount); { each definition get a number, write then the amount of defs to the ibstartdef entry } - ppufile.putlongint(DefList.count); + ppufile.putlongint(defcount); ppufile.writeentry(ibstartdefs); { now write the definition } for i:=0 to DefList.Count-1 do begin def:=tstoreddef(DefList[i]); - def.ppuwrite(ppufile); + if def.is_registered then + def.ppuwrite(ppufile); end; { write end of definitions } ppufile.writeentry(ibenddefs); @@ -590,18 +598,24 @@ implementation procedure tstoredsymtable.writesyms(ppufile:tcompilerppufile); var + symcount, i : longint; sym : Tstoredsym; begin + symcount:=0; + for i:=0 to SymList.Count-1 do + if tstoredsym(SymList[i]).is_registered then + inc(symcount); { each definition get a number, write then the amount of syms and the datasize to the ibsymdef entry } - ppufile.putlongint(SymList.count); + ppufile.putlongint(symcount); ppufile.writeentry(ibstartsyms); { foreach is used to write all symbols } for i:=0 to SymList.Count-1 do begin sym:=tstoredsym(SymList[i]); - sym.ppuwrite(ppufile); + if sym.is_registered then + sym.ppuwrite(ppufile); end; { end of symbols } ppufile.writeentry(ibendsyms); @@ -643,7 +657,77 @@ implementation end; - procedure tstoredsymtable.deref; + procedure tstoredsymtable.buildderef_registered; + var + def : tstoreddef; + sym : tstoredsym; + i : longint; + defidmax, + symidmax: longint; + newbuiltdefderefs, + builtdefderefs, + builtsymderefs: array of boolean; + begin + { tdefs for which we already built the deref } + setlength(builtdefderefs,deflist.count); + { tdefs for which we built the deref in this iteration } + setlength(newbuiltdefderefs,deflist.count); + { syms for which we already built the deref } + setlength(builtsymderefs,symlist.count); + repeat + { we only have to store the defs (recursively) referred by wpo info + or inlined routines in the static symbtable } + + { current number of registered defs/syms } + defidmax:=current_module.deflist.count; + symidmax:=current_module.symlist.count; + + { build the derefs for the registered defs we haven't processed yet } + for i:=0 to DefList.Count-1 do + begin + if not builtdefderefs[i] then + begin + def:=tstoreddef(DefList[i]); + if def.is_registered then + begin + def.buildderef; + newbuiltdefderefs[i]:=true; + builtdefderefs[i]:=true; + end; + end; + end; + { same for the syms } + for i:=0 to SymList.Count-1 do + begin + if not builtsymderefs[i] then + begin + sym:=tstoredsym(SymList[i]); + if sym.is_registered then + begin + sym.buildderef; + builtsymderefs[i]:=true; + end; + end; + end; + { now buildderefimpl for the defs we processed in this iteration } + for i:=0 to DefList.Count-1 do + begin + if newbuiltdefderefs[i] then + begin + newbuiltdefderefs[i]:=false; + tstoreddef(DefList[i]).buildderefimpl; + end; + end; + { stop when no new defs or syms have been registered while processing + the currently registered ones (defs/syms get added to the module's + deflist/symlist when they are registered) } + until + (defidmax=current_module.deflist.count) and + (symidmax=current_module.symlist.count); + end; + + + procedure tstoredsymtable.deref(only_registered: boolean); var i : longint; def : tstoreddef; @@ -656,26 +740,32 @@ implementation for i:=0 to SymList.Count-1 do begin sym:=tstoredsym(SymList[i]); - if sym.typ=typesym then + if (sym.typ=typesym) and + (not only_registered or + sym.is_registered) then sym.deref; end; { interface definitions } for i:=0 to DefList.Count-1 do begin def:=tstoreddef(DefList[i]); - def.deref; + if not only_registered or + def.is_registered then + def.deref; end; { interface symbols } for i:=0 to SymList.Count-1 do begin sym:=tstoredsym(SymList[i]); - if sym.typ<>typesym then + if (not only_registered or + sym.is_registered) and + (sym.typ<>typesym) then sym.deref; end; end; - procedure tstoredsymtable.derefimpl; + procedure tstoredsymtable.derefimpl(only_registered: boolean); var i : longint; def : tstoreddef; @@ -684,7 +774,9 @@ implementation for i:=0 to DefList.Count-1 do begin def:=tstoreddef(DefList[i]); - def.derefimpl; + if not only_registered or + def.is_registered then + def.derefimpl; end; end; @@ -2277,7 +2369,7 @@ implementation inherited ppuload(ppufile); { now we can deref the syms and defs } - deref; + deref(false); end; @@ -2324,7 +2416,7 @@ implementation inherited ppuload(ppufile); { now we can deref the syms and defs } - deref; + deref(false); end; diff --git a/compiler/symtype.pas b/compiler/symtype.pas index a0100f2b1b..6f8e3ff107 100644 --- a/compiler/symtype.pas +++ b/compiler/symtype.pas @@ -52,6 +52,10 @@ interface tgeTSymtable = (gs_none,gs_record,gs_local,gs_para); tdef = class(TDefEntry) + protected + { whether this def is already registered in the unit's def list } + function registered : boolean; + public typesym : tsym; { which type the definition was generated this def } { stabs debugging } stab_number : word; @@ -72,6 +76,7 @@ interface function rtti_mangledname(rt:trttitype):TSymStr;virtual;abstract; function OwnerHierarchyName: string; virtual; abstract; function fullownerhierarchyname:string;virtual;abstract; + function unique_id_str: string; function size:asizeint;virtual;abstract; function packedbitsize:asizeint;virtual; function alignment:shortint;virtual;abstract; @@ -87,6 +92,11 @@ interface function getreusablesymtab: tsymtable; procedure register_created_object_type;virtual; function get_top_level_symtable: tsymtable; + { only valid for registered defs and defs for which a unique id string + has been requested; otherwise, first call register_def } + function deflist_index: longint; + procedure register_def; virtual; abstract; + property is_registered: boolean read registered; end; {************************************************ @@ -99,6 +109,7 @@ interface tsym = class(TSymEntry) protected + function registered : boolean; public fileinfo : tfileposinfo; { size of fileinfo is 10 bytes, so if a >word aligned type would follow, @@ -121,6 +132,8 @@ interface procedure IncRefCountBy(AValue : longint); procedure MaybeCreateRefList; procedure AddRef; + procedure register_sym; virtual; abstract; + property is_registered:boolean read registered; end; tsymarr = array[0..maxlongint div sizeof(pointer)-1] of tsym; @@ -251,6 +264,12 @@ implementation Tdef ****************************************************************************} + function tdef.registered: boolean; + begin + result:=defid>defid_not_registered; + end; + + constructor tdef.create(dt:tdeftyp); begin inherited create; @@ -318,6 +337,26 @@ implementation end; + function tdef.unique_id_str: string; + begin + if (defid=defid_not_registered) or + (defid=defid_registered_nost) then + begin + if not assigned(current_module) then + internalerror(2015102505); + current_module.deflist.Add(self); + { invert the defid to indicate that it was only set because we + needed a unique number -- then add defid_not_registered so we + don't get the values between defid_registered and 0 } + defid:=-(current_module.deflist.Count-1)+defid_not_registered-1; + end; + { use deflist_index so that it will remain the same if def first gets a + defid just for the unique id (as above) and later it gets registered + because it must be saved to the ppu } + result:=hexstr(deflist_index,sizeof(defid)*2); + end; + + function tdef.getparentdef:tdef; begin result:=nil; @@ -384,10 +423,27 @@ implementation result:=tdef(result.defowner).owner; end; + + function tdef.deflist_index: longint; + begin + if defid=0 then + result:=defid + else + internalerror(2015102502) + end; + {**************************************************************************** TSYM (base for all symtypes) ****************************************************************************} + function tsym.registered: boolean; + begin + result:=symid>symid_not_registered; + end; + + constructor tsym.create(st:tsymtyp;const aname:string); begin inherited CreateNotOwned; @@ -680,9 +736,24 @@ implementation begin { TODO: ugly hack} if s is tsym then - st:=FindUnitSymtable(tsym(s).owner) + begin + { if it has been registered but it wasn't put in a symbol table, + this symbol shouldn't be written to a ppu } + if tsym(s).SymId=symid_registered_nost then + Internalerror(2015102504); + if not tsym(s).registered then + tsym(s).register_sym; + st:=FindUnitSymtable(tsym(s).owner) + end else - st:=FindUnitSymtable(tdef(s).owner); + begin + { same as above } + if tdef(s).defid=defid_registered_nost then + Internalerror(2015102505); + if not tdef(s).registered then + tdef(s).register_def; + st:=FindUnitSymtable(tdef(s).owner); + end; if not st.iscurrentunit then begin { register that the unit is needed for resolving }