summaryrefslogtreecommitdiff
path: root/closures/compiler/symsym.pas
diff options
context:
space:
mode:
Diffstat (limited to 'closures/compiler/symsym.pas')
-rw-r--r--closures/compiler/symsym.pas2109
1 files changed, 2109 insertions, 0 deletions
diff --git a/closures/compiler/symsym.pas b/closures/compiler/symsym.pas
new file mode 100644
index 0000000000..c91d3e5d80
--- /dev/null
+++ b/closures/compiler/symsym.pas
@@ -0,0 +1,2109 @@
+{
+ Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
+
+ Implementation for the symbols types of the symtable
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ ****************************************************************************
+}
+unit symsym;
+
+{$i fpcdefs.inc}
+
+interface
+
+ uses
+ { common }
+ cutils,
+ { target }
+ globtype,globals,widestr,constexp,
+ { symtable }
+ symconst,symbase,symtype,symdef,defcmp,
+ { ppu }
+ ppu,finput,
+ cclasses,symnot,
+ { aasm }
+ aasmbase,
+ cpuinfo,cpubase,cgbase,cgutils,parabase
+ ;
+
+ type
+ { this class is the base for all symbol objects }
+ tstoredsym = class(tsym)
+ public
+ constructor create(st:tsymtyp;const n : string);
+ constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ end;
+
+ tlabelsym = class(tstoredsym)
+ used,
+ defined,
+ nonlocal : boolean;
+ { points to the matching node, only valid resultdef pass is run and
+ the goto<->label relation in the node tree is created, should
+ be a tnode }
+ code : pointer;
+
+ { points to the jump buffer }
+ jumpbuf : tstoredsym;
+
+ { when the label is defined in an asm block, this points to the
+ generated asmlabel }
+ asmblocklabel : tasmlabel;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ end;
+
+ tunitsym = class(Tstoredsym)
+ module : tobject; { tmodule }
+ constructor create(const n : string;amodule : tobject);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tnamespacesym = class(Tstoredsym)
+ unitsym:tsym;
+ unitsymderef:tderef;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ terrorsym = class(Tsym)
+ constructor create;
+ end;
+
+ { tprocsym }
+
+ tprocsym = class(tstoredsym)
+ protected
+ FProcdefList : TFPObjectList;
+ FProcdefDerefList : TFPList;
+ public
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ { writes all declarations except the specified one }
+ procedure write_parameter_lists(skipdef:tprocdef);
+ { tests, if all procedures definitions are defined and not }
+ { only forward }
+ procedure check_forward;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function find_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ function find_procdef_bypara(para:TFPObjectList;retdef:tdef;cpoptions:tcompare_paras_options):Tprocdef;
+ function find_procdef_byoptions(ops:tprocoptions): Tprocdef;
+ function find_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ function find_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ function find_procdef_enumerator_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ property ProcdefList:TFPObjectList read FProcdefList;
+ end;
+
+ ttypesym = class(Tstoredsym)
+ public
+ typedef : tdef;
+ typedefderef : tderef;
+ fprettyname : ansistring;
+ constructor create(const n : string;def:tdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function prettyname : string;override;
+ end;
+
+ tabstractvarsym = class(tstoredsym)
+ varoptions : tvaroptions;
+ notifications : Tlinkedlist;
+ varspez : tvarspez; { sets the type of access }
+ varregable : tvarregable;
+ varstate : tvarstate;
+ { Has the address of this variable potentially escaped the }
+ { block in which is was declared? }
+ { could also be part of tabstractnormalvarsym, but there's }
+ { one byte left here till the next 4 byte alignment }
+ addr_taken : boolean;
+ constructor create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getsize : asizeint;
+ function getpackedbitsize : longint;
+ function is_regvar(refpara: boolean):boolean;
+ procedure trigger_notifications(what:Tnotification_flag);
+ function register_notification(flags:Tnotification_flags;
+ callback:Tnotification_callback):cardinal;
+ procedure unregister_notification(id:cardinal);
+ private
+ _vardef : tdef;
+ vardefderef : tderef;
+
+ procedure setvardef(def:tdef);
+ public
+ property vardef: tdef read _vardef write setvardef;
+ end;
+
+ tfieldvarsym = class(tabstractvarsym)
+ fieldoffset : asizeint; { offset in record/object }
+ objcoffsetmangledname: pshortstring; { mangled name of offset, calculated as needed }
+ constructor create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ destructor destroy;override;
+ end;
+
+ tabstractnormalvarsym = class(tabstractvarsym)
+ defaultconstsym : tsym;
+ defaultconstsymderef : tderef;
+ localloc : TLocation; { register/reference for local var }
+ initialloc : TLocation; { initial location so it can still be initialized later after the location was changed by SSA }
+ constructor create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tlocalvarsym = class(tabstractnormalvarsym)
+ constructor create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tparavarsym = class(tabstractnormalvarsym)
+ paraloc : array[tcallercallee] of TCGPara;
+ paranr : word; { position of this parameter }
+ { in MacPas mode, "univ" parameters mean that type checking should
+ be disabled, except that the size of the passed parameter must
+ match the size of the formal parameter }
+ univpara : boolean;
+{$ifdef EXTDEBUG}
+ eqval : tequaltype;
+{$endif EXTDEBUG}
+ constructor create(const n : string;nr:word;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function needs_finalization: boolean;
+ end;
+
+ tstaticvarsym = class(tabstractnormalvarsym)
+ private
+ _mangledname : pshortstring;
+ public
+ section : ansistring;
+ constructor create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ constructor create_dll(const n : string;vsp:tvarspez;def:tdef);
+ constructor create_C(const n,mangled : string;vsp:tvarspez;def:tdef);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ procedure set_mangledname(const s:string);
+ end;
+
+ tabsolutevarsym = class(tabstractvarsym)
+ public
+ abstyp : absolutetyp;
+{$ifdef i386}
+ absseg : boolean;
+{$endif i386}
+ asmname : pshortstring;
+ addroffset : aword;
+ ref : tpropaccesslist;
+ constructor create(const n : string;def:tdef);
+ constructor create_ref(const n : string;def:tdef;_ref:tpropaccesslist);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure buildderef;override;
+ procedure deref;override;
+ function mangledname : string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tpropaccesslisttypes=(palt_none,palt_read,palt_write,palt_stored);
+
+ tpropertysym = class(Tstoredsym)
+ propoptions : tpropertyoptions;
+ overriddenpropsym : tpropertysym;
+ overriddenpropsymderef : tderef;
+ propdef : tdef;
+ propdefderef : tderef;
+ indexdef : tdef;
+ indexdefderef : tderef;
+ index,
+ default : longint;
+ dispid : longint;
+ propaccesslist: array[tpropaccesslisttypes] of tpropaccesslist;
+ parast : tsymtable;
+ constructor create(const n : string);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getsize : asizeint;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tconstvalue = record
+ case integer of
+ 0: (valueord : tconstexprint);
+ 1: (valueordptr : tconstptruint);
+ 2: (valueptr : pointer; len : longint);
+ end;
+
+ tconstsym = class(tstoredsym)
+ constdef : tdef;
+ constdefderef : tderef;
+ consttyp : tconsttyp;
+ value : tconstvalue;
+ constructor create_ord(const n : string;t : tconsttyp;v : tconstexprint;def:tdef);
+ constructor create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;def:tdef);
+ constructor create_ptr(const n : string;t : tconsttyp;v : pointer;def:tdef);
+ constructor create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
+ constructor create_wstring(const n : string;t : tconsttyp;pw:pcompilerwidestring);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tenumsym = class(Tstoredsym)
+ value : longint;
+ definition : tenumdef;
+ definitionderef : tderef;
+ constructor create(const n : string;def : tenumdef;v : longint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tsyssym = class(Tstoredsym)
+ number : longint;
+ constructor create(const n : string;l : longint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ const
+ maxmacrolen=16*1024;
+
+ type
+ pmacrobuffer = ^tmacrobuffer;
+ tmacrobuffer = array[0..maxmacrolen-1] of char;
+
+ tmacro = class(tstoredsym)
+ {Normally true, but false when a previously defined macro is undef-ed}
+ defined : boolean;
+ {True if this is a mac style compiler variable, in which case no macro
+ substitutions shall be done.}
+ is_compiler_var : boolean;
+ {Whether the macro was used. NOTE: A use of a macro which was never defined}
+ {e. g. an IFDEF which returns false, will not be registered as used,}
+ {since there is no place to register its use. }
+ is_used : boolean;
+ buftext : pchar;
+ buflen : longint;
+ constructor create(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ destructor destroy;override;
+ function GetCopy:tmacro;
+ end;
+
+ var
+ generrorsym : tsym;
+
+implementation
+
+ uses
+ { global }
+ verbose,
+ { target }
+ systems,
+ { symtable }
+ defutil,symtable,
+ fmodule,
+ { tree }
+ node,
+ { aasm }
+ aasmtai,aasmdata,
+ { codegen }
+ paramgr,
+ procinfo
+ ;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+{****************************************************************************
+ TSYM (base for all symtypes)
+****************************************************************************}
+
+ constructor tstoredsym.create(st:tsymtyp;const n : string);
+ begin
+ inherited create(st,n);
+ { Register in current_module }
+ if assigned(current_module) then
+ begin
+ current_module.symlist.Add(self);
+ SymId:=current_module.symlist.Count-1;
+ end;
+ end;
+
+
+ constructor tstoredsym.ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ begin
+ SymId:=ppufile.getlongint;
+ inherited Create(st,ppufile.getstring);
+ { Register symbol }
+ current_module.symlist[SymId]:=self;
+ ppufile.getposinfo(fileinfo);
+ visibility:=tvisibility(ppufile.getbyte);
+ ppufile.getsmallset(symoptions);
+ if sp_has_deprecated_msg in symoptions then
+ deprecatedmsg:=stringdup(ppufile.getstring)
+ else
+ deprecatedmsg:=nil;
+ end;
+
+
+ procedure tstoredsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ ppufile.putlongint(SymId);
+ ppufile.putstring(realname);
+ ppufile.putposinfo(fileinfo);
+ ppufile.putbyte(byte(visibility));
+ { symoptions can differ between interface and implementation, except
+ for overload (this is checked in pdecsub.proc_add_definition() )
+
+ These differences can lead to compiler crashes, so ignore them.
+ This does mean that changing e.g. the "deprecated" state of a symbol
+ by itself will not trigger a recompilation of dependent units.
+ }
+ oldintfcrc:=ppufile.do_interface_crc;
+ ppufile.do_interface_crc:=false;
+ ppufile.putsmallset(symoptions);
+ if sp_has_deprecated_msg in symoptions then
+ ppufile.putstring(deprecatedmsg^);
+ ppufile.do_interface_crc:=oldintfcrc;
+ end;
+
+
+ destructor tstoredsym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TLABELSYM
+****************************************************************************}
+
+ constructor tlabelsym.create(const n : string);
+ begin
+ inherited create(labelsym,n);
+ used:=false;
+ defined:=false;
+ nonlocal:=false;
+ code:=nil;
+ end;
+
+
+ constructor tlabelsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(labelsym,ppufile);
+ code:=nil;
+ used:=false;
+ nonlocal:=false;
+ defined:=true;
+ end;
+
+
+ procedure tlabelsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ if owner.symtabletype=globalsymtable then
+ Message(sym_e_ill_label_decl)
+ else
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(iblabelsym);
+ end;
+ end;
+
+
+ function tlabelsym.mangledname:string;
+ begin
+ if not(defined) then
+ begin
+ defined:=true;
+ if nonlocal then
+ current_asmdata.getglobaljumplabel(asmblocklabel)
+ else
+ current_asmdata.getjumplabel(asmblocklabel);
+ end;
+ result:=asmblocklabel.name;
+ end;
+
+{****************************************************************************
+ TUNITSYM
+****************************************************************************}
+
+ constructor tunitsym.create(const n : string;amodule : tobject);
+ begin
+ inherited create(unitsym,n);
+ module:=amodule;
+ end;
+
+ constructor tunitsym.ppuload(ppufile:tcompilerppufile);
+
+ begin
+ inherited ppuload(unitsym,ppufile);
+ module:=nil;
+ end;
+
+ destructor tunitsym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure tunitsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(ibunitsym);
+ end;
+
+{****************************************************************************
+ TNAMESPACESYM
+****************************************************************************}
+
+ constructor tnamespacesym.create(const n : string);
+ begin
+ inherited create(namespacesym,n);
+ unitsym:=nil;
+ end;
+
+ constructor tnamespacesym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(namespacesym,ppufile);
+ ppufile.getderef(unitsymderef);
+ end;
+
+ procedure tnamespacesym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(unitsymderef);
+ ppufile.writeentry(ibnamespacesym);
+ end;
+
+ procedure tnamespacesym.buildderef;
+ begin
+ inherited buildderef;
+ unitsymderef.build(unitsym);
+ end;
+
+ procedure tnamespacesym.deref;
+ begin
+ inherited deref;
+ unitsym:=tsym(unitsymderef.resolve);
+ end;
+
+
+{****************************************************************************
+ TPROCSYM
+****************************************************************************}
+
+ constructor tprocsym.create(const n : string);
+ begin
+ inherited create(procsym,n);
+ FProcdefList:=TFPObjectList.Create(false);
+ FProcdefderefList:=nil;
+ { the tprocdef have their own symoptions, make the procsym
+ always visible }
+ visibility:=vis_public;
+ end;
+
+
+ constructor tprocsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pdderef : tderef;
+ i,
+ pdcnt : longint;
+ begin
+ inherited ppuload(procsym,ppufile);
+ FProcdefList:=TFPObjectList.Create(false);
+ FProcdefDerefList:=TFPList.Create;
+ pdcnt:=ppufile.getword;
+ for i:=1 to pdcnt do
+ begin
+ ppufile.getderef(pdderef);
+ FProcdefDerefList.Add(Pointer(PtrInt(pdderef.dataidx)));
+ end;
+ end;
+
+
+ destructor tprocsym.destroy;
+ begin
+ FProcdefList.Free;
+ if assigned(FProcdefDerefList) then
+ FProcdefDerefList.Free;
+ inherited destroy;
+ end;
+
+
+ procedure tprocsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ i : longint;
+ d : tderef;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putword(FProcdefDerefList.Count);
+ for i:=0 to FProcdefDerefList.Count-1 do
+ begin
+ d.dataidx:=PtrInt(FProcdefDerefList[i]);
+ ppufile.putderef(d);
+ end;
+ ppufile.writeentry(ibprocsym);
+ end;
+
+
+ procedure tprocsym.write_parameter_lists(skipdef:tprocdef);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if pd<>skipdef then
+ MessagePos1(pd.fileinfo,sym_h_param_list,pd.fullprocname(false));
+ end;
+ end;
+
+
+ procedure tprocsym.check_forward;
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if (pd.owner=owner) and (pd.forwarddef) then
+ begin
+ { For mode macpas. Make implicit externals (procedures declared in the interface
+ section which do not have a counterpart in the implementation)
+ to be an imported procedure }
+ if (m_mac in current_settings.modeswitches) and
+ (pd.interfacedef) then
+ begin
+ pd.setmangledname(target_info.CPrefix+tprocdef(pd).procsym.realname);
+ if (not current_module.interface_only) then
+ MessagePos1(pd.fileinfo,sym_w_forward_not_resolved,pd.fullprocname(false));
+ end
+ else
+ begin
+ MessagePos1(pd.fileinfo,sym_e_forward_not_resolved,pd.fullprocname(false));
+ end;
+ { Turn further error messages off }
+ pd.forwarddef:=false;
+ end;
+ end;
+ end;
+
+
+ procedure tprocsym.buildderef;
+ var
+ i : longint;
+ pd : tprocdef;
+ d : tderef;
+ begin
+ if not assigned(FProcdefDerefList) then
+ FProcdefDerefList:=TFPList.Create
+ else
+ FProcdefDerefList.Clear;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ { only write the proc definitions that belong
+ to this procsym and are in the global symtable }
+ if pd.owner=owner then
+ begin
+ d.build(pd);
+ FProcdefDerefList.Add(Pointer(PtrInt(d.dataidx)));
+ end;
+ end;
+ end;
+
+
+ procedure tprocsym.deref;
+ var
+ i : longint;
+ pd : tprocdef;
+ d : tderef;
+ begin
+ { Clear all procdefs }
+ ProcdefList.Clear;
+ if not assigned(FProcdefDerefList) then
+ internalerror(200611031);
+ for i:=0 to FProcdefDerefList.Count-1 do
+ begin
+ d.dataidx:=PtrInt(FProcdefDerefList[i]);
+ pd:=tprocdef(d.resolve);
+ ProcdefList.Add(pd);
+ end;
+ end;
+
+
+ function Tprocsym.Find_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ result:=nil;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if pd.proctypeoption=pt then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+
+
+ function Tprocsym.Find_procdef_bypara(para:TFPObjectList;retdef:tdef;
+ cpoptions:tcompare_paras_options):Tprocdef;
+ var
+ i : longint;
+ pd : tprocdef;
+ eq : tequaltype;
+ begin
+ result:=nil;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if assigned(retdef) then
+ eq:=compare_defs(retdef,pd.returndef,nothingn)
+ else
+ eq:=te_equal;
+ if (eq>=te_equal) or
+ ((cpo_allowconvert in cpoptions) and (eq>te_incompatible)) then
+ begin
+ eq:=compare_paras(para,pd.paras,cp_value_equal_const,cpoptions);
+ if (eq>=te_equal) or
+ ((cpo_allowconvert in cpoptions) and (eq>te_incompatible)) then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+ end;
+
+ function tprocsym.find_procdef_byoptions(ops: tprocoptions): Tprocdef;
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ result:=nil;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if ops * pd.procoptions = ops then
+ begin
+ result:=pd;
+ exit;
+ end;
+ end;
+ end;
+
+ function Tprocsym.Find_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ var
+ i : longint;
+ bestpd,
+ pd : tprocdef;
+ eq,besteq : tequaltype;
+ sym: tsym;
+ ps: tprocsym;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for procvardef. When there are multiple
+ matches it returns nil.}
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ ps:=self;
+ repeat
+ for i:=0 to ps.ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ps.ProcdefList[i]);
+ eq:=proc_to_procvar_equal(pd,d,false);
+ if eq>=te_convert_l1 then
+ begin
+ { multiple procvars with the same equal level }
+ if assigned(bestpd) and
+ (besteq=eq) then
+ exit;
+ if eq>besteq then
+ begin
+ besteq:=eq;
+ bestpd:=pd;
+ end;
+ end;
+ end;
+ { maybe TODO: also search class helpers? -- this code is similar to
+ what happens in htypechk in
+ tcallcandidates.collect_overloads_in_struct: keep searching in
+ parent types in case the currently found procdef is marked as
+ "overload" and we haven't found a proper match yet }
+ if assigned(ps.owner.defowner) and
+ (ps.owner.defowner.typ=objectdef) and
+ assigned(tobjectdef(ps.owner.defowner).childof) and
+ (not assigned(bestpd) or
+ (po_overload in bestpd.procoptions)) then
+ begin
+ sym:=tsym(tobjectdef(ps.owner.defowner).childof.symtable.find(ps.name));
+ if assigned(sym) and
+ (sym.typ=procsym) then
+ ps:=tprocsym(sym)
+ else
+ ps:=nil;
+ end
+ else
+ ps:=nil;
+ until (besteq>=te_equal) or
+ not assigned(ps);
+ result:=bestpd;
+ end;
+
+
+ function Tprocsym.Find_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ var
+ paraidx, realparamcount,
+ i, j : longint;
+ bestpd,
+ hpd,
+ pd : tprocdef;
+ convtyp : tconverttype;
+ eq : tequaltype;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for fromdef and todef. }
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if (pd.owner.symtabletype=staticsymtable) and not pd.owner.iscurrentunit then
+ continue;
+ if (equal_defs(todef,pd.returndef) or
+ { shortstrings of different lengths are ok as result }
+ (is_shortstring(todef) and is_shortstring(pd.returndef))) and
+ { the result type must be always really equal and not an alias,
+ if you mess with this code, check tw4093 }
+ ((todef=pd.returndef) or
+ (
+ not(df_unique in todef.defoptions) and
+ not(df_unique in pd.returndef.defoptions)
+ )
+ ) then
+ begin
+ paraidx:=0;
+ { ignore vs_hidden parameters }
+ while (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (vo_is_hidden_para in tparavarsym(pd.paras[paraidx]).varoptions) do
+ inc(paraidx);
+ realparamcount:=0;
+ for j := 0 to pd.paras.Count-1 do
+ if assigned(pd.paras[j]) and not (vo_is_hidden_para in tparavarsym(pd.paras[j]).varoptions) then
+ inc(realparamcount);
+ if (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (realparamcount = 1) then
+ begin
+ eq:=compare_defs_ext(fromdef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
+
+ { alias? if yes, only l1 choice,
+ if you mess with this code, check tw4093 }
+ if (eq=te_exact) and
+ (fromdef<>tparavarsym(pd.paras[paraidx]).vardef) and
+ ((df_unique in fromdef.defoptions) or
+ (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
+ eq:=te_convert_l1;
+
+ if eq=te_exact then
+ begin
+ besteq:=eq;
+ result:=pd;
+ exit;
+ end;
+ if eq>besteq then
+ begin
+ bestpd:=pd;
+ besteq:=eq;
+ end;
+ end;
+ end;
+ end;
+ result:=bestpd;
+ end;
+
+ function Tprocsym.find_procdef_enumerator_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ var
+ paraidx, realparamcount,
+ i, j : longint;
+ bestpd,
+ hpd,
+ pd : tprocdef;
+ current : tpropertysym;
+ convtyp : tconverttype;
+ eq : tequaltype;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for fromdef and todef. }
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ for i:=0 to ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(ProcdefList[i]);
+ if (pd.owner.symtabletype=staticsymtable) and not pd.owner.iscurrentunit then
+ continue;
+ if not (is_class_or_interface_or_object(pd.returndef) or is_record(pd.returndef)) then
+ continue;
+ current := tpropertysym(tabstractrecorddef(pd.returndef).search_enumerator_current);
+ if (current = nil) then
+ continue;
+ // compare current result def with the todef
+ if (equal_defs(todef, current.propdef) or
+ { shortstrings of different lengths are ok as result }
+ (is_shortstring(todef) and is_shortstring(current.propdef))) and
+ { the result type must be always really equal and not an alias,
+ if you mess with this code, check tw4093 }
+ ((todef=current.propdef) or
+ (
+ not(df_unique in todef.defoptions) and
+ not(df_unique in current.propdef.defoptions)
+ )
+ ) then
+ begin
+ paraidx:=0;
+ { ignore vs_hidden parameters }
+ while (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (vo_is_hidden_para in tparavarsym(pd.paras[paraidx]).varoptions) do
+ inc(paraidx);
+ realparamcount:=0;
+ for j := 0 to pd.paras.Count-1 do
+ if assigned(pd.paras[j]) and not (vo_is_hidden_para in tparavarsym(pd.paras[j]).varoptions) then
+ inc(realparamcount);
+ if (paraidx<pd.paras.count) and
+ assigned(pd.paras[paraidx]) and
+ (realparamcount = 1) then
+ begin
+ eq:=compare_defs_ext(fromdef,tparavarsym(pd.paras[paraidx]).vardef,nothingn,convtyp,hpd,[]);
+
+ { alias? if yes, only l1 choice,
+ if you mess with this code, check tw4093 }
+ if (eq=te_exact) and
+ (fromdef<>tparavarsym(pd.paras[paraidx]).vardef) and
+ ((df_unique in fromdef.defoptions) or
+ (df_unique in tparavarsym(pd.paras[paraidx]).vardef.defoptions)) then
+ eq:=te_convert_l1;
+
+ if eq=te_exact then
+ begin
+ besteq:=eq;
+ result:=pd;
+ exit;
+ end;
+ if eq>besteq then
+ begin
+ bestpd:=pd;
+ besteq:=eq;
+ end;
+ end;
+ end;
+ end;
+ result:=bestpd;
+ end;
+
+
+{****************************************************************************
+ TERRORSYM
+****************************************************************************}
+
+ constructor terrorsym.create;
+ begin
+ inherited create(errorsym,'');
+ end;
+
+{****************************************************************************
+ TPROPERTYSYM
+****************************************************************************}
+
+ constructor tpropertysym.create(const n : string);
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ inherited create(propertysym,n);
+ propoptions:=[];
+ index:=0;
+ default:=0;
+ propdef:=nil;
+ indexdef:=nil;
+ parast:=nil;
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap]:=tpropaccesslist.create;
+ end;
+
+
+ constructor tpropertysym.ppuload(ppufile:tcompilerppufile);
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ inherited ppuload(propertysym,ppufile);
+ ppufile.getsmallset(propoptions);
+ if ppo_overrides in propoptions then
+ ppufile.getderef(overriddenpropsymderef);
+ ppufile.getderef(propdefderef);
+ index:=ppufile.getlongint;
+ default:=ppufile.getlongint;
+ ppufile.getderef(indexdefderef);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap]:=ppufile.getpropaccesslist;
+ if [ppo_hasparameters,ppo_overrides]*propoptions=[ppo_hasparameters] then
+ begin
+ parast:=tparasymtable.create(nil,0);
+ tparasymtable(parast).ppuload(ppufile);
+ end
+ else
+ parast:=nil;
+ end;
+
+
+ destructor tpropertysym.destroy;
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap].free;
+ parast.free;
+ inherited destroy;
+ end;
+
+
+ procedure tpropertysym.buildderef;
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ propdefderef.build(propdef);
+ indexdefderef.build(indexdef);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap].buildderef;
+ if ppo_overrides in propoptions then
+ overriddenpropsymderef.build(overriddenpropsym)
+ else
+ if ppo_hasparameters in propoptions then
+ tparasymtable(parast).buildderef;
+ end;
+
+
+ procedure tpropertysym.deref;
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ indexdef:=tdef(indexdefderef.resolve);
+ propdef:=tdef(propdefderef.resolve);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ propaccesslist[pap].resolve;
+
+ if ppo_overrides in propoptions then
+ begin
+ overriddenpropsym:=tpropertysym(overriddenpropsymderef.resolve);
+ if ppo_hasparameters in propoptions then
+ parast:=overriddenpropsym.parast.getcopy;
+ end
+ else
+ if ppo_hasparameters in propoptions then
+ tparasymtable(parast).deref
+ end;
+
+
+ function tpropertysym.getsize : asizeint;
+ begin
+ getsize:=0;
+ end;
+
+
+ procedure tpropertysym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ pap : tpropaccesslisttypes;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putsmallset(propoptions);
+ if ppo_overrides in propoptions then
+ ppufile.putderef(overriddenpropsymderef);
+ ppufile.putderef(propdefderef);
+ ppufile.putlongint(index);
+ ppufile.putlongint(default);
+ ppufile.putderef(indexdefderef);
+ for pap:=low(tpropaccesslisttypes) to high(tpropaccesslisttypes) do
+ ppufile.putpropaccesslist(propaccesslist[pap]);
+ ppufile.writeentry(ibpropertysym);
+ if [ppo_hasparameters,ppo_overrides]*propoptions=[ppo_hasparameters] then
+ tparasymtable(parast).ppuwrite(ppufile);
+ end;
+
+
+{****************************************************************************
+ TABSTRACTVARSYM
+****************************************************************************}
+
+ constructor tabstractvarsym.create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(st,n);
+ vardef:=def;
+ varspez:=vsp;
+ varstate:=vs_declared;
+ varoptions:=vopts;
+ end;
+
+
+ constructor tabstractvarsym.ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(st,ppufile);
+ varstate:=vs_readwritten;
+ varspez:=tvarspez(ppufile.getbyte);
+ varregable:=tvarregable(ppufile.getbyte);
+ addr_taken:=boolean(ppufile.getbyte);
+ ppufile.getderef(vardefderef);
+ ppufile.getsmallset(varoptions);
+ end;
+
+
+ destructor tabstractvarsym.destroy;
+ begin
+ if assigned(notifications) then
+ notifications.destroy;
+ inherited destroy;
+ end;
+
+
+ procedure tabstractvarsym.buildderef;
+ begin
+ vardefderef.build(vardef);
+ end;
+
+
+ procedure tabstractvarsym.deref;
+ var
+ oldvarregable: tvarregable;
+ begin
+ { setting the vardef also updates varregable. We just loaded this }
+ { value from a ppu, so it must not be changed (e.g. tw7817a.pp/ }
+ { tw7817b.pp: the address is taken of a local variable in an }
+ { inlined procedure -> must remain non-regable when inlining) }
+ oldvarregable:=varregable;
+ vardef:=tdef(vardefderef.resolve);
+ varregable:=oldvarregable;
+ end;
+
+
+ procedure tabstractvarsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(varspez));
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putbyte(byte(varregable));
+ ppufile.putbyte(byte(addr_taken));
+ ppufile.do_crc:=oldintfcrc;
+ ppufile.putderef(vardefderef);
+ ppufile.putsmallset(varoptions);
+ end;
+
+
+ function tabstractvarsym.getsize : asizeint;
+ begin
+ if assigned(vardef) and
+ ((vardef.typ<>arraydef) or
+ is_dynamic_array(vardef) or
+ (tarraydef(vardef).highrange>=tarraydef(vardef).lowrange)) then
+ result:=vardef.size
+ else
+ result:=0;
+ end;
+
+
+ function tabstractvarsym.getpackedbitsize : longint;
+ begin
+ { bitpacking is only done for ordinals }
+ if not is_ordinal(vardef) then
+ internalerror(2006082010);
+ result:=vardef.packedbitsize;
+ end;
+
+
+ function tabstractvarsym.is_regvar(refpara: boolean):boolean;
+ begin
+ { Register variables are not allowed in the following cases:
+ - regvars are disabled
+ - exceptions are used (after an exception is raised the contents of the
+ registers is not valid anymore)
+ - it has a local copy
+ - the value needs to be in memory (i.e. reference counted) }
+ result:=(cs_opt_regvar in current_settings.optimizerswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) and
+ not(pi_has_interproclabel in current_procinfo.flags) and
+ not(vo_has_local_copy in varoptions) and
+ ((refpara and
+ (varregable <> vr_none)) or
+ (not refpara and
+ not(varregable in [vr_none,vr_addr])))
+{$if not defined(powerpc) and not defined(powerpc64)}
+ and ((vardef.typ <> recorddef) or
+ (varregable = vr_addr) or
+ not(varstate in [vs_written,vs_readwritten]));
+{$endif}
+ end;
+
+
+ procedure tabstractvarsym.trigger_notifications(what:Tnotification_flag);
+
+ var n:Tnotification;
+
+ begin
+ if assigned(notifications) then
+ begin
+ n:=Tnotification(notifications.first);
+ while assigned(n) do
+ begin
+ if what in n.flags then
+ n.callback(what,self);
+ n:=Tnotification(n.next);
+ end;
+ end;
+ end;
+
+ function Tabstractvarsym.register_notification(flags:Tnotification_flags;callback:
+ Tnotification_callback):cardinal;
+
+ var n:Tnotification;
+
+ begin
+ if not assigned(notifications) then
+ notifications:=Tlinkedlist.create;
+ n:=Tnotification.create(flags,callback);
+ register_notification:=n.id;
+ notifications.concat(n);
+ end;
+
+ procedure Tabstractvarsym.unregister_notification(id:cardinal);
+
+ var n:Tnotification;
+
+ begin
+ if not assigned(notifications) then
+ internalerror(200212311)
+ else
+ begin
+ n:=Tnotification(notifications.first);
+ while assigned(n) do
+ begin
+ if n.id=id then
+ begin
+ notifications.remove(n);
+ n.destroy;
+ exit;
+ end;
+ n:=Tnotification(n.next);
+ end;
+ internalerror(200212311)
+ end;
+ end;
+
+ procedure tabstractvarsym.setvardef(def:tdef);
+ begin
+ _vardef := def;
+ { can we load the value into a register ? }
+ if not assigned(owner) or
+ (owner.symtabletype in [localsymtable,parasymtable]) or
+ (
+ (owner.symtabletype=staticsymtable) and
+ not(cs_create_pic in current_settings.moduleswitches)
+ ) then
+ begin
+ if tstoreddef(vardef).is_intregable then
+ varregable:=vr_intreg
+ else
+{ $warning TODO: no fpu regvar in staticsymtable yet, need initialization with 0 }
+ if {(
+ not assigned(owner) or
+ (owner.symtabletype<>staticsymtable)
+ ) and }
+ tstoreddef(vardef).is_fpuregable then
+ begin
+ if use_vectorfpu(vardef) then
+ varregable:=vr_mmreg
+ else
+ varregable:=vr_fpureg;
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TFIELDVARSYM
+****************************************************************************}
+
+ constructor tfieldvarsym.create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(fieldvarsym,n,vsp,def,vopts);
+ fieldoffset:=-1;
+ end;
+
+
+ constructor tfieldvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(fieldvarsym,ppufile);
+ fieldoffset:=ppufile.getaint;
+ end;
+
+
+ procedure tfieldvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putaint(fieldoffset);
+ ppufile.writeentry(ibfieldvarsym);
+ end;
+
+
+ function tfieldvarsym.mangledname:string;
+ var
+ srsym : tsym;
+ srsymtable : tsymtable;
+ begin
+ if sp_static in symoptions then
+ begin
+ if searchsym(lower(owner.name^)+'_'+name,srsym,srsymtable) then
+ result:=srsym.mangledname
+ { when generating the debug info for the module in which the }
+ { symbol is defined, the localsymtable of that module is }
+ { already popped from the symtablestack }
+ else if searchsym_in_module(current_module,lower(owner.name^)+'_'+name,srsym,srsymtable) then
+ result:=srsym.mangledname
+ else
+ internalerror(2007012501);
+ end
+ else if is_objcclass(tdef(owner.defowner)) then
+ begin
+ if assigned(objcoffsetmangledname) then
+ result:=objcoffsetmangledname^
+ else
+ begin
+ result:=target_info.cprefix+'OBJC_IVAR_$_'+tobjectdef(owner.defowner).objextname^+'.'+RealName;
+ objcoffsetmangledname:=stringdup(result);
+ end;
+ end
+ else
+ result:=inherited mangledname;
+ end;
+
+
+ destructor tfieldvarsym.destroy;
+ begin
+ stringdispose(objcoffsetmangledname);
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TABSTRACTNORMALVARSYM
+****************************************************************************}
+
+ constructor tabstractnormalvarsym.create(st:tsymtyp;const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(st,n,vsp,def,vopts);
+ fillchar(localloc,sizeof(localloc),0);
+ fillchar(initialloc,sizeof(initialloc),0);
+ defaultconstsym:=nil;
+ end;
+
+
+ constructor tabstractnormalvarsym.ppuload(st:tsymtyp;ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(st,ppufile);
+ fillchar(localloc,sizeof(localloc),0);
+ fillchar(initialloc,sizeof(initialloc),0);
+ ppufile.getderef(defaultconstsymderef);
+ end;
+
+
+ procedure tabstractnormalvarsym.buildderef;
+ begin
+ inherited buildderef;
+ defaultconstsymderef.build(defaultconstsym);
+ end;
+
+
+ procedure tabstractnormalvarsym.deref;
+ begin
+ inherited deref;
+ defaultconstsym:=tsym(defaultconstsymderef.resolve);
+ end;
+
+
+ procedure tabstractnormalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(defaultconstsymderef);
+ end;
+
+
+{****************************************************************************
+ Tstaticvarsym
+****************************************************************************}
+
+ constructor tstaticvarsym.create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(staticvarsym,n,vsp,def,vopts);
+ _mangledname:=nil;
+ end;
+
+
+ constructor tstaticvarsym.create_dll(const n : string;vsp:tvarspez;def:tdef);
+ begin
+ tstaticvarsym(self).create(n,vsp,def,[vo_is_dll_var]);
+ end;
+
+
+ constructor tstaticvarsym.create_C(const n,mangled : string;vsp:tvarspez;def:tdef);
+ begin
+ tstaticvarsym(self).create(n,vsp,def,[]);
+ set_mangledname(mangled);
+ end;
+
+
+ constructor tstaticvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(staticvarsym,ppufile);
+ if vo_has_mangledname in varoptions then
+ _mangledname:=stringdup(ppufile.getstring)
+ else
+ _mangledname:=nil;
+ if vo_has_section in varoptions then
+ section:=ppufile.getansistring;
+ end;
+
+
+ destructor tstaticvarsym.destroy;
+ begin
+ if assigned(_mangledname) then
+ begin
+{$ifdef MEMDEBUG}
+ memmanglednames.start;
+{$endif MEMDEBUG}
+ stringdispose(_mangledname);
+{$ifdef MEMDEBUG}
+ memmanglednames.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tstaticvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ if vo_has_mangledname in varoptions then
+ ppufile.putstring(_mangledname^);
+ if vo_has_section in varoptions then
+ ppufile.putansistring(section);
+ ppufile.writeentry(ibstaticvarsym);
+ end;
+
+
+ function tstaticvarsym.mangledname:string;
+ var
+ prefix : string[2];
+ begin
+ if not assigned(_mangledname) then
+ begin
+ if (vo_is_typed_const in varoptions) then
+ prefix:='TC'
+ else
+ prefix:='U';
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(make_mangledname(prefix,owner,name)));
+ {$else}
+ _mangledname:=stringdup(make_mangledname(prefix,owner,name));
+ {$endif}
+ end;
+ result:=_mangledname^;
+ end;
+
+
+ procedure tstaticvarsym.set_mangledname(const s:string);
+ begin
+ stringdispose(_mangledname);
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(s));
+ {$else}
+ _mangledname:=stringdup(s);
+ {$endif}
+ include(varoptions,vo_has_mangledname);
+ end;
+
+
+{****************************************************************************
+ TLOCALVARSYM
+****************************************************************************}
+
+ constructor tlocalvarsym.create(const n : string;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(localvarsym,n,vsp,def,vopts);
+ end;
+
+
+ constructor tlocalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(localvarsym,ppufile);
+ end;
+
+
+ procedure tlocalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(iblocalvarsym);
+ end;
+
+
+{****************************************************************************
+ TPARAVARSYM
+****************************************************************************}
+
+ constructor tparavarsym.create(const n : string;nr:word;vsp:tvarspez;def:tdef;vopts:tvaroptions);
+ begin
+ inherited create(paravarsym,n,vsp,def,vopts);
+ if (vsp in [vs_var,vs_value,vs_const,vs_constref]) then
+ varstate := vs_initialised;
+ paranr:=nr;
+ paraloc[calleeside].init;
+ paraloc[callerside].init;
+ end;
+
+
+ destructor tparavarsym.destroy;
+ begin
+ paraloc[calleeside].done;
+ paraloc[callerside].done;
+ inherited destroy;
+ end;
+
+
+ constructor tparavarsym.ppuload(ppufile:tcompilerppufile);
+ var
+ b : byte;
+ begin
+ inherited ppuload(paravarsym,ppufile);
+ paranr:=ppufile.getword;
+ univpara:=boolean(ppufile.getbyte);
+
+ { The var state of parameter symbols is fixed after writing them so
+ we write them to the unit file.
+ This enables constant folding for inline procedures loaded from units
+ }
+ varstate:=tvarstate(ppufile.getbyte);
+
+ paraloc[calleeside].init;
+ paraloc[callerside].init;
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ paraloc[callerside].alignment:=ppufile.getbyte;
+ b:=ppufile.getbyte;
+ if b<>sizeof(paraloc[callerside].location^) then
+ internalerror(200411154);
+ ppufile.getdata(paraloc[callerside].add_location^,sizeof(paraloc[callerside].location^));
+ paraloc[callerside].size:=paraloc[callerside].location^.size;
+ paraloc[callerside].intsize:=tcgsize2size[paraloc[callerside].size];
+ end;
+ end;
+
+
+ procedure tparavarsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ oldintfcrc : boolean;
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putword(paranr);
+ ppufile.putbyte(byte(univpara));
+
+ { The var state of parameter symbols is fixed after writing them so
+ we write them to the unit file.
+ This enables constant folding for inline procedures loaded from units
+ }
+ oldintfcrc:=ppufile.do_crc;
+ ppufile.do_crc:=false;
+ ppufile.putbyte(ord(varstate));
+ ppufile.do_crc:=oldintfcrc;
+
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ paraloc[callerside].check_simple_location;
+ ppufile.putbyte(sizeof(paraloc[callerside].alignment));
+ ppufile.putbyte(sizeof(paraloc[callerside].location^));
+ ppufile.putdata(paraloc[callerside].location^,sizeof(paraloc[callerside].location^));
+ end;
+ ppufile.writeentry(ibparavarsym);
+ end;
+
+ function tparavarsym.needs_finalization:boolean;
+ begin
+ result:=(varspez=vs_value) and
+ (is_managed_type(vardef) or
+ (
+ (not (tabstractprocdef(owner.defowner).proccalloption in cdecl_pocalls)) and
+ (not paramanager.use_stackalloc) and
+ (is_open_array(vardef) or is_array_of_const(vardef))
+ )
+ );
+ end;
+
+{****************************************************************************
+ TABSOLUTEVARSYM
+****************************************************************************}
+
+ constructor tabsolutevarsym.create(const n : string;def:tdef);
+ begin
+ inherited create(absolutevarsym,n,vs_value,def,[]);
+ ref:=nil;
+ end;
+
+
+ constructor tabsolutevarsym.create_ref(const n : string;def:tdef;_ref:tpropaccesslist);
+ begin
+ inherited create(absolutevarsym,n,vs_value,def,[]);
+ ref:=_ref;
+ end;
+
+
+ destructor tabsolutevarsym.destroy;
+ begin
+ if assigned(ref) then
+ ref.free;
+ inherited destroy;
+ end;
+
+
+ constructor tabsolutevarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(absolutevarsym,ppufile);
+ ref:=nil;
+ asmname:=nil;
+ abstyp:=absolutetyp(ppufile.getbyte);
+{$ifdef i386}
+ absseg:=false;
+{$endif i386}
+ case abstyp of
+ tovar :
+ ref:=ppufile.getpropaccesslist;
+ toasm :
+ asmname:=stringdup(ppufile.getstring);
+ toaddr :
+ begin
+ addroffset:=ppufile.getaword;
+{$ifdef i386}
+ absseg:=boolean(ppufile.getbyte);
+{$endif i386}
+ end;
+ end;
+ end;
+
+
+ procedure tabsolutevarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(abstyp));
+ case abstyp of
+ tovar :
+ ppufile.putpropaccesslist(ref);
+ toasm :
+ ppufile.putstring(asmname^);
+ toaddr :
+ begin
+ ppufile.putaword(addroffset);
+{$ifdef i386}
+ ppufile.putbyte(byte(absseg));
+{$endif i386}
+ end;
+ end;
+ ppufile.writeentry(ibabsolutevarsym);
+ end;
+
+
+ procedure tabsolutevarsym.buildderef;
+ begin
+ inherited buildderef;
+ if (abstyp=tovar) then
+ ref.buildderef;
+ end;
+
+
+ procedure tabsolutevarsym.deref;
+ begin
+ inherited deref;
+ { own absolute deref }
+ if (abstyp=tovar) then
+ ref.resolve;
+ end;
+
+
+ function tabsolutevarsym.mangledname : string;
+ begin
+ case abstyp of
+ toasm :
+ mangledname:=asmname^;
+ toaddr :
+ mangledname:='$'+tostr(addroffset);
+ else
+ internalerror(200411062);
+ end;
+ end;
+
+
+{****************************************************************************
+ TCONSTSYM
+****************************************************************************}
+
+ constructor tconstsym.create_ord(const n : string;t : tconsttyp;v : tconstexprint;def:tdef);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueord:=v;
+ constdef:=def;
+ end;
+
+
+ constructor tconstsym.create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;def:tdef);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueordptr:=v;
+ constdef:=def;
+ end;
+
+
+ constructor tconstsym.create_ptr(const n : string;t : tconsttyp;v : pointer;def:tdef);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueptr:=v;
+ constdef:=def;
+ end;
+
+
+ constructor tconstsym.create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ value.valueptr:=str;
+ constdef:=nil;
+ value.len:=l;
+ end;
+
+
+ constructor tconstsym.create_wstring(const n : string;t : tconsttyp;pw:pcompilerwidestring);
+ begin
+ inherited create(constsym,n);
+ fillchar(value, sizeof(value), #0);
+ consttyp:=t;
+ pcompilerwidestring(value.valueptr):=pw;
+ constdef:=nil;
+ value.len:=getlengthwidestring(pw);
+ end;
+
+
+ constructor tconstsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pd : pbestreal;
+ ps : pnormalset;
+ pc : pchar;
+ pw : pcompilerwidestring;
+ i : longint;
+ begin
+ inherited ppuload(constsym,ppufile);
+ constdef:=nil;
+ consttyp:=tconsttyp(ppufile.getbyte);
+ fillchar(value, sizeof(value), #0);
+ case consttyp of
+ constord :
+ begin
+ ppufile.getderef(constdefderef);
+ value.valueord:=ppufile.getexprint;
+ end;
+ constpointer :
+ begin
+ ppufile.getderef(constdefderef);
+ value.valueordptr:=ppufile.getptruint;
+ end;
+ constwstring :
+ begin
+ initwidestring(pw);
+ setlengthwidestring(pw,ppufile.getlongint);
+ { don't use getdata, because the compilerwidechars may have to
+ be byteswapped
+ }
+{$if sizeof(tcompilerwidechar) = 2}
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=ppufile.getword;
+{$elseif sizeof(tcompilerwidechar) = 4}
+ for i:=0 to pw^.len-1 do
+ pw^.data[i]:=cardinal(ppufile.getlongint);
+{$else}
+ {$error Unsupported tcompilerwidechar size}
+{$endif}
+ pcompilerwidestring(value.valueptr):=pw;
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ value.len:=ppufile.getlongint;
+ getmem(pc,value.len+1);
+ ppufile.getdata(pc^,value.len);
+ pc[value.len]:=#0;
+ value.valueptr:=pc;
+ end;
+ constreal :
+ begin
+ new(pd);
+ pd^:=ppufile.getreal;
+ value.valueptr:=pd;
+ end;
+ constset :
+ begin
+ ppufile.getderef(constdefderef);
+ new(ps);
+ ppufile.getnormalset(ps^);
+ value.valueptr:=ps;
+ end;
+ constguid :
+ begin
+ new(pguid(value.valueptr));
+ ppufile.getdata(value.valueptr^,sizeof(tguid));
+ end;
+ constnil : ;
+ else
+ Message1(unit_f_ppu_invalid_entry,tostr(ord(consttyp)));
+ end;
+ end;
+
+
+ destructor tconstsym.destroy;
+ begin
+ case consttyp of
+ conststring,
+ constresourcestring :
+ freemem(pchar(value.valueptr),value.len+1);
+ constwstring :
+ donewidestring(pcompilerwidestring(value.valueptr));
+ constreal :
+ dispose(pbestreal(value.valueptr));
+ constset :
+ dispose(pnormalset(value.valueptr));
+ constguid :
+ dispose(pguid(value.valueptr));
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tconstsym.buildderef;
+ begin
+ if consttyp in [constord,constpointer,constset] then
+ constdefderef.build(constdef);
+ end;
+
+
+ procedure tconstsym.deref;
+ begin
+ if consttyp in [constord,constpointer,constset] then
+ constdef:=tdef(constdefderef.resolve);
+ end;
+
+
+ procedure tconstsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(consttyp));
+ case consttyp of
+ constnil : ;
+ constord :
+ begin
+ ppufile.putderef(constdefderef);
+ ppufile.putexprint(value.valueord);
+ end;
+ constpointer :
+ begin
+ ppufile.putderef(constdefderef);
+ ppufile.putptruint(value.valueordptr);
+ end;
+ constwstring :
+ begin
+ ppufile.putlongint(getlengthwidestring(pcompilerwidestring(value.valueptr)));
+ ppufile.putdata(pcompilerwidestring(value.valueptr)^.data^,pcompilerwidestring(value.valueptr)^.len*sizeof(tcompilerwidechar));
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ ppufile.putlongint(value.len);
+ ppufile.putdata(pchar(value.valueptr)^,value.len);
+ end;
+ constreal :
+ ppufile.putreal(pbestreal(value.valueptr)^);
+ constset :
+ begin
+ ppufile.putderef(constdefderef);
+ ppufile.putnormalset(value.valueptr^);
+ end;
+ constguid :
+ ppufile.putdata(value.valueptr^,sizeof(tguid));
+ else
+ internalerror(13);
+ end;
+ ppufile.writeentry(ibconstsym);
+ end;
+
+
+{****************************************************************************
+ TENUMSYM
+****************************************************************************}
+
+ constructor tenumsym.create(const n : string;def : tenumdef;v : longint);
+ begin
+ inherited create(enumsym,n);
+ definition:=def;
+ value:=v;
+ end;
+
+
+ constructor tenumsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(enumsym,ppufile);
+ ppufile.getderef(definitionderef);
+ value:=ppufile.getlongint;
+ end;
+
+
+ procedure tenumsym.buildderef;
+ begin
+ definitionderef.build(definition);
+ end;
+
+
+ procedure tenumsym.deref;
+ begin
+ definition:=tenumdef(definitionderef.resolve);
+ end;
+
+ procedure tenumsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(definitionderef);
+ ppufile.putlongint(value);
+ ppufile.writeentry(ibenumsym);
+ end;
+
+
+{****************************************************************************
+ TTYPESYM
+****************************************************************************}
+
+ constructor ttypesym.create(const n : string;def:tdef);
+
+ begin
+ inherited create(typesym,n);
+ typedef:=def;
+ { register the typesym for the definition }
+ if assigned(typedef) and
+ (typedef.typ<>errordef) and
+ not(assigned(typedef.typesym)) then
+ typedef.typesym:=self;
+ end;
+
+
+ constructor ttypesym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(typesym,ppufile);
+ ppufile.getderef(typedefderef);
+ fprettyname:=ppufile.getansistring;
+ end;
+
+
+ procedure ttypesym.buildderef;
+ begin
+ typedefderef.build(typedef);
+ end;
+
+
+ procedure ttypesym.deref;
+ begin
+ typedef:=tdef(typedefderef.resolve);
+ end;
+
+
+ procedure ttypesym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putderef(typedefderef);
+ ppufile.putansistring(fprettyname);
+ ppufile.writeentry(ibtypesym);
+ end;
+
+
+ function ttypesym.prettyname : string;
+ begin
+ if fprettyname<>'' then
+ result:=fprettyname
+ else
+ result:=inherited prettyname;
+ end;
+
+
+{****************************************************************************
+ TSYSSYM
+****************************************************************************}
+
+ constructor tsyssym.create(const n : string;l : longint);
+ begin
+ inherited create(syssym,n);
+ number:=l;
+ end;
+
+ constructor tsyssym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(syssym,ppufile);
+ number:=ppufile.getlongint;
+ end;
+
+ destructor tsyssym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure tsyssym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putlongint(number);
+ ppufile.writeentry(ibsyssym);
+ end;
+
+
+{*****************************************************************************
+ TMacro
+*****************************************************************************}
+
+ constructor tmacro.create(const n : string);
+ begin
+ inherited create(macrosym,n);
+ owner:=nil;
+ defined:=false;
+ is_used:=false;
+ is_compiler_var:=false;
+ buftext:=nil;
+ buflen:=0;
+ end;
+
+ constructor tmacro.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(macrosym,ppufile);
+ defined:=boolean(ppufile.getbyte);
+ is_compiler_var:=boolean(ppufile.getbyte);
+ is_used:=false;
+ buflen:= ppufile.getlongint;
+ if buflen > 0 then
+ begin
+ getmem(buftext, buflen);
+ ppufile.getdata(buftext^, buflen)
+ end
+ else
+ buftext:=nil;
+ end;
+
+ destructor tmacro.destroy;
+ begin
+ if assigned(buftext) then
+ freemem(buftext);
+ inherited destroy;
+ end;
+
+ procedure tmacro.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(defined));
+ ppufile.putbyte(byte(is_compiler_var));
+ ppufile.putlongint(buflen);
+ if buflen > 0 then
+ ppufile.putdata(buftext^,buflen);
+ ppufile.writeentry(ibmacrosym);
+ end;
+
+
+ function tmacro.GetCopy:tmacro;
+ var
+ p : tmacro;
+ begin
+ p:=tmacro.create(realname);
+ p.defined:=defined;
+ p.is_used:=is_used;
+ p.is_compiler_var:=is_compiler_var;
+ p.buflen:=buflen;
+ if assigned(buftext) then
+ begin
+ getmem(p.buftext,buflen);
+ move(buftext^,p.buftext^,buflen);
+ end;
+ Result:=p;
+ end;
+
+end.