summaryrefslogtreecommitdiff
path: root/compiler/symsym.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/symsym.pas')
-rw-r--r--compiler/symsym.pas2349
1 files changed, 2349 insertions, 0 deletions
diff --git a/compiler/symsym.pas b/compiler/symsym.pas
new file mode 100644
index 0000000000..71d8c093c8
--- /dev/null
+++ b/compiler/symsym.pas
@@ -0,0 +1,2349 @@
+{
+ 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,
+ { symtable }
+ symconst,symbase,symtype,symdef,defcmp,
+ { ppu }
+ ppu,
+ 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(const n : string);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);virtual;
+ end;
+
+ tlabelsym = class(tstoredsym)
+ used,
+ defined : boolean;
+ { points to the matching node, only valid resulttype pass is run and
+ the goto<->label relation in the node tree is created, should
+ be a tnode }
+ code : pointer;
+
+ { 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;
+ end;
+
+ tunitsym = class(Tstoredsym)
+ unitsymtable : tsymtable;
+ constructor create(const n : string;ref : tsymtable);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ terrorsym = class(Tsym)
+ constructor create;
+ end;
+
+ Tprocdefcallback = procedure(p:Tprocdef;arg:pointer);
+
+ tprocsym = class(tstoredsym)
+ protected
+ pdlistfirst,
+ pdlistlast : pprocdeflist; { linked list of overloaded procdefs }
+ function getprocdef(nr:cardinal):Tprocdef;
+ public
+ procdef_count : byte;
+ overloadchecked : boolean;
+ property procdef[nr:cardinal]:Tprocdef read getprocdef;
+ 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 unchain_overload;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure addprocdef(p:tprocdef);
+ procedure addprocdef_deref(const d:tderef);
+ procedure add_para_match_to(Aprocsym:Tprocsym;cpoptions:tcompare_paras_options);
+ procedure concat_procdefs_to(s:Tprocsym);
+ procedure foreach_procdef_static(proc2call:Tprocdefcallback;arg:pointer);
+ function first_procdef:Tprocdef;
+ function last_procdef:Tprocdef;
+ function search_procdef_nopara_boolret:Tprocdef;
+ function search_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ function search_procdef_bypara(para:tlist;retdef:tdef;cpoptions:tcompare_paras_options):Tprocdef;
+ function search_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ function search_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;override;
+ { currobjdef is the object def to assume, this is necessary for protected and
+ private,
+ context is the object def we're really in, this is for the strict stuff
+ }
+ function is_visible_for_object(currobjdef:tdef;context:tdef):boolean;override;
+ end;
+
+ ttypesym = class(Tstoredsym)
+ restype : ttype;
+ constructor create(const n : string;const tt : ttype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function gettypedef:tdef;override;
+ procedure load_references(ppufile:tcompilerppufile;locals:boolean);override;
+ function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;override;
+ end;
+
+ tabstractvarsym = class(tstoredsym)
+ varoptions : tvaroptions;
+ varspez : tvarspez; { sets the type of access }
+ varregable : tvarregable;
+ varstate : tvarstate;
+ notifications : Tlinkedlist;
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getsize : longint;
+ function is_regvar:boolean;
+ procedure trigger_notifications(what:Tnotification_flag);
+ function register_notification(flags:Tnotification_flags;
+ callback:Tnotification_callback):cardinal;
+ procedure unregister_notification(id:cardinal);
+ private
+ procedure setvartype(const newtype: ttype);
+ _vartype : ttype;
+ public
+ property vartype: ttype read _vartype write setvartype;
+ end;
+
+ tfieldvarsym = class(tabstractvarsym)
+ fieldoffset : aint; { offset in record/object }
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tabstractnormalvarsym = class(tabstractvarsym)
+ defaultconstsym : tsym;
+ defaultconstsymderef : tderef;
+ localloc : TLocation; { register/reference for local var }
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ end;
+
+ tlocalvarsym = class(tabstractnormalvarsym)
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;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 }
+{$ifdef EXTDEBUG}
+ eqval : tequaltype;
+{$endif EXTDEBUG}
+ constructor create(const n : string;nr:word;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tglobalvarsym = class(tabstractnormalvarsym)
+ private
+ _mangledname : pstring;
+ public
+ constructor create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ constructor create_dll(const n : string;vsp:tvarspez;const tt : ttype);
+ constructor create_C(const n,mangled : string;vsp:tvarspez;const tt : ttype);
+ 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 : pstring;
+ addroffset : aint;
+ ref : tsymlist;
+ constructor create(const n : string;const tt : ttype);
+ constructor create_ref(const n : string;const tt : ttype;_ref:tsymlist);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure buildderef;override;
+ procedure deref;override;
+ function mangledname : string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ end;
+
+ tpropertysym = class(Tstoredsym)
+ propoptions : tpropertyoptions;
+ propoverriden : tpropertysym;
+ propoverridenderef : tderef;
+ proptype,
+ indextype : ttype;
+ index,
+ default : longint;
+ readaccess,
+ writeaccess,
+ storedaccess : tsymlist;
+ constructor create(const n : string);
+ destructor destroy;override;
+ constructor ppuload(ppufile:tcompilerppufile);
+ function getsize : longint;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function gettypedef:tdef;override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure dooverride(overriden:tpropertysym);
+ end;
+
+ ttypedconstsym = class(tstoredsym)
+ private
+ _mangledname : pstring;
+ public
+ typedconsttype : ttype;
+ is_writable : boolean;
+ constructor create(const n : string;p : tdef;writable : boolean);
+ constructor createtype(const n : string;const tt : ttype;writable : boolean);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ function mangledname : string;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ function getsize:longint;
+ end;
+
+ tconstvalue = record
+ case integer of
+ 0: (valueord : tconstexprint);
+ 1: (valueordptr : tconstptruint);
+ 2: (valueptr : pointer; len : longint);
+ end;
+
+ tconstsym = class(tstoredsym)
+ consttype : ttype;
+ consttyp : tconsttyp;
+ value : tconstvalue;
+ resstrindex : longint; { needed for resource strings }
+ constructor create_ord(const n : string;t : tconsttyp;v : tconstexprint;const tt:ttype);
+ constructor create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;const tt:ttype);
+ constructor create_ptr(const n : string;t : tconsttyp;v : pointer;const tt:ttype);
+ 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;
+ nextenum : tenumsym;
+ constructor create(const n : string;def : tenumdef;v : longint);
+ constructor ppuload(ppufile:tcompilerppufile);
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ procedure buildderef;override;
+ procedure deref;override;
+ procedure order;
+ 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;
+ end;
+
+ { compiler generated symbol to point to rtti and init/finalize tables }
+ trttisym = class(tstoredsym)
+ private
+ _mangledname : pstring;
+ public
+ lab : tasmsymbol;
+ rttityp : trttitype;
+ constructor create(const n:string;rt:trttitype);
+ constructor ppuload(ppufile:tcompilerppufile);
+ destructor destroy;override;
+ procedure ppuwrite(ppufile:tcompilerppufile);override;
+ function mangledname:string;override;
+ function get_label:tasmsymbol;
+ end;
+
+ var
+ generrorsym : tsym;
+
+implementation
+
+ uses
+ { global }
+ verbose,
+ { target }
+ systems,
+ { symtable }
+ defutil,symtable,
+ { tree }
+ node,
+ { aasm }
+ { codegen }
+ paramgr,cresstr,
+ procinfo
+ ;
+
+{****************************************************************************
+ Helpers
+****************************************************************************}
+
+{****************************************************************************
+ TSYM (base for all symtypes)
+****************************************************************************}
+
+ constructor tstoredsym.create(const n : string);
+ begin
+ inherited create(n);
+ end;
+
+
+ constructor tstoredsym.ppuload(ppufile:tcompilerppufile);
+ var
+ nr : word;
+ s : string;
+ begin
+ nr:=ppufile.getword;
+ s:=ppufile.getstring;
+ if s[1]='$' then
+ inherited createname(copy(s,2,255))
+ else
+ inherited createname(upper(s));
+ _realname:=stringdup(s);
+ typ:=abstractsym;
+ { force the correct indexnr. must be after create! }
+ indexnr:=nr;
+ ppufile.getposinfo(fileinfo);
+ ppufile.getsmallset(symoptions);
+ lastref:=nil;
+ defref:=nil;
+ refs:=0;
+ lastwritten:=nil;
+ refcount:=0;
+ isstabwritten := false;
+ end;
+
+
+ procedure tstoredsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ ppufile.putword(indexnr);
+ ppufile.putstring(_realname^);
+ ppufile.putposinfo(fileinfo);
+ ppufile.putsmallset(symoptions);
+ end;
+
+
+ destructor tstoredsym.destroy;
+ begin
+ if assigned(defref) then
+ begin
+{$ifdef MEMDEBUG}
+ membrowser.start;
+{$endif MEMDEBUG}
+ defref.freechain;
+ defref.free;
+{$ifdef MEMDEBUG}
+ membrowser.stop;
+{$endif MEMDEBUG}
+ end;
+ inherited destroy;
+ end;
+
+
+{****************************************************************************
+ TLABELSYM
+****************************************************************************}
+
+ constructor tlabelsym.create(const n : string);
+ begin
+ inherited create(n);
+ typ:=labelsym;
+ used:=false;
+ defined:=false;
+ code:=nil;
+ end;
+
+
+ constructor tlabelsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=labelsym;
+ code:=nil;
+ used:=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;
+
+
+{****************************************************************************
+ TUNITSYM
+****************************************************************************}
+
+ constructor tunitsym.create(const n : string;ref : tsymtable);
+ var
+ old_make_ref : boolean;
+ begin
+ old_make_ref:=make_ref;
+ make_ref:=false;
+ inherited create(n);
+ make_ref:=old_make_ref;
+ typ:=unitsym;
+ unitsymtable:=ref;
+ end;
+
+ constructor tunitsym.ppuload(ppufile:tcompilerppufile);
+
+ begin
+ inherited ppuload(ppufile);
+ typ:=unitsym;
+ unitsymtable:=nil;
+ end;
+
+ destructor tunitsym.destroy;
+ begin
+ inherited destroy;
+ end;
+
+ procedure tunitsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.writeentry(ibunitsym);
+ end;
+
+{****************************************************************************
+ TPROCSYM
+****************************************************************************}
+
+ constructor tprocsym.create(const n : string);
+
+ begin
+ inherited create(n);
+ typ:=procsym;
+ pdlistfirst:=nil;
+ pdlistlast:=nil;
+ owner:=nil;
+ { the tprocdef have their own symoptions, make the procsym
+ always visible }
+ symoptions:=[sp_public];
+ overloadchecked:=false;
+ procdef_count:=0;
+ end;
+
+
+ constructor tprocsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pdderef : tderef;
+ i,n : longint;
+ begin
+ inherited ppuload(ppufile);
+ typ:=procsym;
+ pdlistfirst:=nil;
+ pdlistlast:=nil;
+ procdef_count:=0;
+ n:=ppufile.getword;
+ for i:=1to n do
+ begin
+ ppufile.getderef(pdderef);
+ addprocdef_deref(pdderef);
+ end;
+ overloadchecked:=false;
+ end;
+
+
+ destructor tprocsym.destroy;
+ var
+ hp,p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ hp:=p^.next;
+ dispose(p);
+ p:=hp;
+ end;
+ inherited destroy;
+ end;
+
+
+ procedure tprocsym.ppuwrite(ppufile:tcompilerppufile);
+ var
+ p : pprocdeflist;
+ n : word;
+ begin
+ inherited ppuwrite(ppufile);
+ { count procdefs }
+ n:=0;
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ { only write the proc definitions that belong
+ to this procsym and are in the global symtable }
+ if p^.def.owner=owner then
+ inc(n);
+ p:=p^.next;
+ end;
+ ppufile.putword(n);
+ { write procdefs }
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ { only write the proc definitions that belong
+ to this procsym and are in the global symtable }
+ if p^.def.owner=owner then
+ ppufile.putderef(p^.defderef);
+ p:=p^.next;
+ end;
+ ppufile.writeentry(ibprocsym);
+ end;
+
+
+ procedure tprocsym.write_parameter_lists(skipdef:tprocdef);
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if p^.def<>skipdef then
+ MessagePos1(p^.def.fileinfo,sym_h_param_list,p^.def.fullprocname(false));
+ p:=p^.next;
+ end;
+ end;
+
+ {Makes implicit externals (procedures declared in the interface
+ section which do not have a counterpart in the implementation)
+ to be an imported procedure. For mode macpas.}
+ procedure import_implict_external(pd:tabstractprocdef);
+
+ begin
+ tprocdef(pd).forwarddef:=false;
+ tprocdef(pd).setmangledname(target_info.CPrefix+tprocdef(pd).procsym.realname);
+ end;
+
+
+ procedure tprocsym.check_forward;
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if (p^.def.owner=owner) and (p^.def.forwarddef) then
+ begin
+ if (m_mac in aktmodeswitches) and (p^.def.interfacedef) then
+ import_implict_external(p^.def)
+ else
+ begin
+ MessagePos1(p^.def.fileinfo,sym_e_forward_not_resolved,p^.def.fullprocname(false));
+ { Turn further error messages off }
+ p^.def.forwarddef:=false;
+ end
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.buildderef;
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if p^.def.owner=owner then
+ p^.defderef.build(p^.def);
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.deref;
+ var
+ p : pprocdeflist;
+ begin
+ { We have removed the overloaded entries, because they
+ are not valid anymore and we can't deref them because
+ the unit were they come from is not necessary in
+ our uses clause (PFV) }
+ unchain_overload;
+ { Deref our own procdefs }
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if not(
+ (p^.def=nil) or
+ (p^.def.owner=owner)
+ ) then
+ internalerror(200310291);
+ p^.def:=tprocdef(p^.defderef.resolve);
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.addprocdef(p:tprocdef);
+ var
+ pd : pprocdeflist;
+ begin
+ new(pd);
+ pd^.def:=p;
+ pd^.defderef.reset;
+ pd^.next:=nil;
+ { Add at end of list to keep always
+ a correct order, also after loading from ppu }
+ if assigned(pdlistlast) then
+ begin
+ pdlistlast^.next:=pd;
+ pdlistlast:=pd;
+ end
+ else
+ begin
+ pdlistfirst:=pd;
+ pdlistlast:=pd;
+ end;
+ inc(procdef_count);
+ end;
+
+
+ procedure tprocsym.addprocdef_deref(const d:tderef);
+ var
+ pd : pprocdeflist;
+ begin
+ new(pd);
+ pd^.def:=nil;
+ pd^.defderef:=d;
+ pd^.next:=nil;
+ { Add at end of list to keep always
+ a correct order, also after loading from ppu }
+ if assigned(pdlistlast) then
+ begin
+ pdlistlast^.next:=pd;
+ pdlistlast:=pd;
+ end
+ else
+ begin
+ pdlistfirst:=pd;
+ pdlistlast:=pd;
+ end;
+ inc(procdef_count);
+ end;
+
+
+ function Tprocsym.getprocdef(nr:cardinal):Tprocdef;
+ var
+ i : cardinal;
+ pd : pprocdeflist;
+ begin
+ pd:=pdlistfirst;
+ for i:=2 to nr do
+ begin
+ if not assigned(pd) then
+ internalerror(200209051);
+ pd:=pd^.next;
+ end;
+ getprocdef:=pd^.def;
+ end;
+
+
+ procedure Tprocsym.add_para_match_to(Aprocsym:Tprocsym;cpoptions:tcompare_paras_options);
+ var
+ pd:pprocdeflist;
+ begin
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ if Aprocsym.search_procdef_bypara(pd^.def.paras,nil,cpoptions)=nil then
+ Aprocsym.addprocdef(pd^.def);
+ pd:=pd^.next;
+ end;
+ end;
+
+
+ procedure Tprocsym.concat_procdefs_to(s:Tprocsym);
+ var
+ pd : pprocdeflist;
+ begin
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ s.addprocdef(pd^.def);
+ pd:=pd^.next;
+ end;
+ end;
+
+
+ function Tprocsym.first_procdef:Tprocdef;
+ begin
+ if assigned(pdlistfirst) then
+ first_procdef:=pdlistfirst^.def
+ else
+ first_procdef:=nil;
+ end;
+
+
+ function Tprocsym.last_procdef:Tprocdef;
+ begin
+ if assigned(pdlistlast) then
+ last_procdef:=pdlistlast^.def
+ else
+ last_procdef:=nil;
+ end;
+
+
+ procedure Tprocsym.foreach_procdef_static(proc2call:Tprocdefcallback;arg:pointer);
+ var
+ p : pprocdeflist;
+ begin
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ proc2call(p^.def,arg);
+ p:=p^.next;
+ end;
+ end;
+
+
+ function Tprocsym.search_procdef_nopara_boolret:Tprocdef;
+ var
+ p : pprocdeflist;
+ begin
+ search_procdef_nopara_boolret:=nil;
+ p:=pdlistfirst;
+ while p<>nil do
+ begin
+ if (p^.def.maxparacount=0) and
+ is_boolean(p^.def.rettype.def) then
+ begin
+ search_procdef_nopara_boolret:=p^.def;
+ break;
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+ function Tprocsym.search_procdef_bytype(pt:Tproctypeoption):Tprocdef;
+ var
+ p : pprocdeflist;
+ begin
+ search_procdef_bytype:=nil;
+ p:=pdlistfirst;
+ while p<>nil do
+ begin
+ if p^.def.proctypeoption=pt then
+ begin
+ search_procdef_bytype:=p^.def;
+ break;
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+ function Tprocsym.search_procdef_bypara(para:tlist;retdef:tdef;
+ cpoptions:tcompare_paras_options):Tprocdef;
+ var
+ pd : pprocdeflist;
+ eq : tequaltype;
+ begin
+ search_procdef_bypara:=nil;
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ if assigned(retdef) then
+ eq:=compare_defs(retdef,pd^.def.rettype.def,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^.def.paras,cp_value_equal_const,cpoptions);
+ if (eq>=te_equal) or
+ ((cpo_allowconvert in cpoptions) and (eq>te_incompatible)) then
+ begin
+ search_procdef_bypara:=pd^.def;
+ break;
+ end;
+ end;
+ pd:=pd^.next;
+ end;
+ end;
+
+ function Tprocsym.search_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
+ var
+ pd : pprocdeflist;
+ eq,besteq : tequaltype;
+ bestpd : tprocdef;
+ begin
+ { This function will return the pprocdef of pprocsym that
+ is the best match for procvardef. When there are multiple
+ matches it returns nil.}
+ search_procdef_byprocvardef:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ eq:=proc_to_procvar_equal(pd^.def,d);
+ if eq>=te_equal 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^.def;
+ end;
+ end;
+ pd:=pd^.next;
+ end;
+ search_procdef_byprocvardef:=bestpd;
+ end;
+
+
+ function Tprocsym.search_procdef_assignment_operator(fromdef,todef:tdef;var besteq:tequaltype):Tprocdef;
+ var
+ convtyp : tconverttype;
+ pd : pprocdeflist;
+ bestpd : tprocdef;
+ eq : tequaltype;
+ hpd : tprocdef;
+ i : byte;
+ begin
+ result:=nil;
+ bestpd:=nil;
+ besteq:=te_incompatible;
+ pd:=pdlistfirst;
+ while assigned(pd) do
+ begin
+ if equal_defs(todef,pd^.def.rettype.def) and
+ { the result type must be always really equal and not an alias,
+ if you mess with this code, check tw4093 }
+ ((todef=pd^.def.rettype.def) or
+ (
+ not(df_unique in todef.defoptions) and
+ not(df_unique in pd^.def.rettype.def.defoptions)
+ )
+ ) then
+ begin
+ i:=0;
+ { ignore vs_hidden parameters }
+ while (i<pd^.def.paras.count) and
+ assigned(pd^.def.paras[i]) and
+ (vo_is_hidden_para in tparavarsym(pd^.def.paras[i]).varoptions) do
+ inc(i);
+ if (i<pd^.def.paras.count) and
+ assigned(pd^.def.paras[i]) then
+ begin
+ eq:=compare_defs_ext(fromdef,tparavarsym(pd^.def.paras[i]).vartype.def,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^.def.paras[i]).vartype.def) and
+ ((df_unique in fromdef.defoptions) or
+ (df_unique in tparavarsym(pd^.def.paras[i]).vartype.def.defoptions)) then
+ eq:=te_convert_l1;
+
+ if eq=te_exact then
+ begin
+ besteq:=eq;
+ result:=pd^.def;
+ exit;
+ end;
+ if eq>besteq then
+ begin
+ bestpd:=pd^.def;
+ besteq:=eq;
+ end;
+ end;
+ end;
+ pd:=pd^.next;
+ end;
+ result:=bestpd;
+ end;
+
+
+ function tprocsym.write_references(ppufile:tcompilerppufile;locals:boolean) : boolean;
+ var
+ p : pprocdeflist;
+ begin
+ write_references:=false;
+ if not inherited write_references(ppufile,locals) then
+ exit;
+ write_references:=true;
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if p^.def.owner=owner then
+ p^.def.write_references(ppufile,locals);
+ p:=p^.next;
+ end;
+ end;
+
+
+ procedure tprocsym.unchain_overload;
+ var
+ p,hp : pprocdeflist;
+ begin
+ { remove all overloaded procdefs from the
+ procdeflist that are not in the current symtable }
+ overloadchecked:=false;
+ p:=pdlistfirst;
+ { reset new lists }
+ pdlistfirst:=nil;
+ pdlistlast:=nil;
+ while assigned(p) do
+ begin
+ hp:=p^.next;
+ { only keep the proc definitions:
+ - are not deref'd (def=nil)
+ - are in the same symtable as the procsym (for example both
+ are in the staticsymtable) }
+ if (p^.def=nil) or
+ (p^.def.owner=owner) then
+ begin
+ { keep, add to list }
+ if assigned(pdlistlast) then
+ begin
+ pdlistlast^.next:=p;
+ pdlistlast:=p;
+ end
+ else
+ begin
+ pdlistfirst:=p;
+ pdlistlast:=p;
+ end;
+ p^.next:=nil;
+ end
+ else
+ begin
+ { remove }
+ dispose(p);
+ dec(procdef_count);
+ end;
+ p:=hp;
+ end;
+ end;
+
+
+ function tprocsym.is_visible_for_object(currobjdef:tdef;context:tdef):boolean;
+ var
+ p : pprocdeflist;
+ begin
+ { This procsym is visible, when there is at least
+ one of the procdefs visible }
+ result:=false;
+ p:=pdlistfirst;
+ while assigned(p) do
+ begin
+ if (p^.def.owner=owner) and
+ p^.def.is_visible_for_object(tobjectdef(currobjdef)) then
+ begin
+ result:=true;
+ exit;
+ end;
+ p:=p^.next;
+ end;
+ end;
+
+
+
+{****************************************************************************
+ TERRORSYM
+****************************************************************************}
+
+ constructor terrorsym.create;
+ begin
+ inherited create('');
+ typ:=errorsym;
+ end;
+
+{****************************************************************************
+ TPROPERTYSYM
+****************************************************************************}
+
+ constructor tpropertysym.create(const n : string);
+ begin
+ inherited create(n);
+ typ:=propertysym;
+ propoptions:=[];
+ index:=0;
+ default:=0;
+ proptype.reset;
+ indextype.reset;
+ readaccess:=tsymlist.create;
+ writeaccess:=tsymlist.create;
+ storedaccess:=tsymlist.create;
+ end;
+
+
+ constructor tpropertysym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=propertysym;
+ ppufile.getsmallset(propoptions);
+ if (ppo_is_override in propoptions) then
+ begin
+ ppufile.getderef(propoverridenderef);
+ { we need to have these objects initialized }
+ readaccess:=tsymlist.create;
+ writeaccess:=tsymlist.create;
+ storedaccess:=tsymlist.create;
+ end
+ else
+ begin
+ ppufile.gettype(proptype);
+ index:=ppufile.getlongint;
+ default:=ppufile.getlongint;
+ ppufile.gettype(indextype);
+ readaccess:=ppufile.getsymlist;
+ writeaccess:=ppufile.getsymlist;
+ storedaccess:=ppufile.getsymlist;
+ end;
+ end;
+
+
+ destructor tpropertysym.destroy;
+ begin
+ readaccess.free;
+ writeaccess.free;
+ storedaccess.free;
+ inherited destroy;
+ end;
+
+
+ function tpropertysym.gettypedef:tdef;
+ begin
+ gettypedef:=proptype.def;
+ end;
+
+
+ procedure tpropertysym.buildderef;
+ begin
+ if (ppo_is_override in propoptions) then
+ begin
+ propoverridenderef.build(propoverriden);
+ end
+ else
+ begin
+ proptype.buildderef;
+ indextype.buildderef;
+ readaccess.buildderef;
+ writeaccess.buildderef;
+ storedaccess.buildderef;
+ end;
+ end;
+
+
+ procedure tpropertysym.deref;
+ begin
+ if (ppo_is_override in propoptions) then
+ begin
+ propoverriden:=tpropertysym(propoverridenderef.resolve);
+ dooverride(propoverriden);
+ end
+ else
+ begin
+ proptype.resolve;
+ indextype.resolve;
+ readaccess.resolve;
+ writeaccess.resolve;
+ storedaccess.resolve;
+ end;
+ end;
+
+
+ function tpropertysym.getsize : longint;
+ begin
+ getsize:=0;
+ end;
+
+
+ procedure tpropertysym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putsmallset(propoptions);
+ if (ppo_is_override in propoptions) then
+ ppufile.putderef(propoverridenderef)
+ else
+ begin
+ ppufile.puttype(proptype);
+ ppufile.putlongint(index);
+ ppufile.putlongint(default);
+ ppufile.puttype(indextype);
+ ppufile.putsymlist(readaccess);
+ ppufile.putsymlist(writeaccess);
+ ppufile.putsymlist(storedaccess);
+ end;
+ ppufile.writeentry(ibpropertysym);
+ end;
+
+
+ procedure tpropertysym.dooverride(overriden:tpropertysym);
+ begin
+ propoverriden:=overriden;
+ proptype:=overriden.proptype;
+ propoptions:=overriden.propoptions+[ppo_is_override];
+ index:=overriden.index;
+ default:=overriden.default;
+ indextype:=overriden.indextype;
+ readaccess.free;
+ readaccess:=overriden.readaccess.getcopy;
+ writeaccess.free;
+ writeaccess:=overriden.writeaccess.getcopy;
+ storedaccess.free;
+ storedaccess:=overriden.storedaccess.getcopy;
+ end;
+
+
+{****************************************************************************
+ TABSTRACTVARSYM
+****************************************************************************}
+
+ constructor tabstractvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n);
+ vartype:=tt;
+ varspez:=vsp;
+ varstate:=vs_declared;
+ varoptions:=vopts;
+ end;
+
+
+ constructor tabstractvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ varstate:=vs_used;
+ varspez:=tvarspez(ppufile.getbyte);
+ varregable:=tvarregable(ppufile.getbyte);
+ ppufile.gettype(_vartype);
+ ppufile.getsmallset(varoptions);
+ end;
+
+
+ destructor tabstractvarsym.destroy;
+ begin
+ if assigned(notifications) then
+ notifications.destroy;
+ inherited destroy;
+ end;
+
+
+ procedure tabstractvarsym.buildderef;
+ begin
+ vartype.buildderef;
+ end;
+
+
+ procedure tabstractvarsym.deref;
+ begin
+ vartype.resolve;
+ 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.do_crc:=oldintfcrc;
+ ppufile.puttype(vartype);
+ ppufile.putsmallset(varoptions);
+ end;
+
+
+ function tabstractvarsym.getsize : longint;
+ begin
+ if assigned(vartype.def) and
+ ((vartype.def.deftype<>arraydef) or
+ tarraydef(vartype.def).isDynamicArray or
+ (tarraydef(vartype.def).highrange>=tarraydef(vartype.def).lowrange)) then
+ result:=vartype.def.size
+ else
+ result:=0;
+ end;
+
+
+ function tabstractvarsym.is_regvar: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_regvars in aktglobalswitches) and
+ not(pi_has_assembler_block in current_procinfo.flags) and
+ not(pi_uses_exceptions in current_procinfo.flags) and
+ not(vo_has_local_copy in varoptions) and
+ (varregable<>vr_none);
+ 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.setvartype(const newtype: ttype);
+ begin
+ _vartype := newtype;
+ { 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 aktmoduleswitches)
+ ) then
+ begin
+ if tstoreddef(vartype.def).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(vartype.def).is_fpuregable then
+ begin
+{$ifdef x86}
+ if use_sse(vartype.def) then
+ varregable:=vr_mmreg
+ else
+{$else x86}
+ varregable:=vr_fpureg;
+{$endif x86}
+ end;
+ end;
+ end;
+
+
+{****************************************************************************
+ TFIELDVARSYM
+****************************************************************************}
+
+ constructor tfieldvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=fieldvarsym;
+ fieldoffset:=0;
+ end;
+
+
+ constructor tfieldvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=fieldvarsym;
+ fieldoffset:=ppufile.getaint;
+ end;
+
+
+ procedure tfieldvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putaint(fieldoffset);
+ ppufile.writeentry(ibfieldvarsym);
+ end;
+
+
+{****************************************************************************
+ TABSTRACTNORMALVARSYM
+****************************************************************************}
+
+ constructor tabstractnormalvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ fillchar(localloc,sizeof(localloc),0);
+ defaultconstsym:=nil;
+ end;
+
+
+ constructor tabstractnormalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ fillchar(localloc,sizeof(localloc),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;
+
+
+{****************************************************************************
+ TGLOBALVARSYM
+****************************************************************************}
+
+ constructor tglobalvarsym.create(const n : string;vsp:tvarspez;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=globalvarsym;
+ _mangledname:=nil;
+ end;
+
+
+ constructor tglobalvarsym.create_dll(const n : string;vsp:tvarspez;const tt : ttype);
+ begin
+ tglobalvarsym(self).create(n,vsp,tt,[vo_is_dll_var]);
+ end;
+
+
+ constructor tglobalvarsym.create_C(const n,mangled : string;vsp:tvarspez;const tt : ttype);
+ begin
+ tglobalvarsym(self).create(n,vsp,tt,[]);
+ set_mangledname(mangled);
+ end;
+
+
+ constructor tglobalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=globalvarsym;
+ if vo_has_mangledname in varoptions then
+ _mangledname:=stringdup(ppufile.getstring)
+ else
+ _mangledname:=nil;
+ end;
+
+
+ destructor tglobalvarsym.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 tglobalvarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ if vo_has_mangledname in varoptions then
+ ppufile.putstring(_mangledname^);
+ ppufile.writeentry(ibglobalvarsym);
+ end;
+
+
+ function tglobalvarsym.mangledname:string;
+ begin
+ if not assigned(_mangledname) then
+ begin
+ {$ifdef compress}
+ _mangledname:=stringdup(minilzw_encode(make_mangledname('U',owner,name)));
+ {$else}
+ _mangledname:=stringdup(make_mangledname('U',owner,name));
+ {$endif}
+ end;
+ result:=_mangledname^;
+ end;
+
+
+ procedure tglobalvarsym.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;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=localvarsym;
+ end;
+
+
+ constructor tlocalvarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=localvarsym;
+ 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;const tt : ttype;vopts:tvaroptions);
+ begin
+ inherited create(n,vsp,tt,vopts);
+ typ:=paravarsym;
+ 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(ppufile);
+ paranr:=ppufile.getword;
+ paraloc[calleeside].init;
+ paraloc[callerside].init;
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ 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;
+ typ:=paravarsym;
+ end;
+
+
+ procedure tparavarsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putword(paranr);
+ if vo_has_explicit_paraloc in varoptions then
+ begin
+ paraloc[callerside].check_simple_location;
+ ppufile.putbyte(sizeof(paraloc[callerside].location^));
+ ppufile.putdata(paraloc[callerside].location^,sizeof(paraloc[callerside].location^));
+ end;
+ ppufile.writeentry(ibparavarsym);
+ end;
+
+
+{****************************************************************************
+ TABSOLUTEVARSYM
+****************************************************************************}
+
+ constructor tabsolutevarsym.create(const n : string;const tt : ttype);
+ begin
+ inherited create(n,vs_value,tt,[]);
+ typ:=absolutevarsym;
+ ref:=nil;
+ end;
+
+
+ constructor tabsolutevarsym.create_ref(const n : string;const tt : ttype;_ref:tsymlist);
+ begin
+ inherited create(n,vs_value,tt,[]);
+ typ:=absolutevarsym;
+ ref:=_ref;
+ end;
+
+
+ destructor tabsolutevarsym.destroy;
+ begin
+ if assigned(ref) then
+ ref.free;
+ inherited destroy;
+ end;
+
+
+ constructor tabsolutevarsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=absolutevarsym;
+ ref:=nil;
+ asmname:=nil;
+ abstyp:=absolutetyp(ppufile.getbyte);
+{$ifdef i386}
+ absseg:=false;
+{$endif i386}
+ case abstyp of
+ tovar :
+ ref:=ppufile.getsymlist;
+ toasm :
+ asmname:=stringdup(ppufile.getstring);
+ toaddr :
+ begin
+ addroffset:=ppufile.getaint;
+{$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.putsymlist(ref);
+ toasm :
+ ppufile.putstring(asmname^);
+ toaddr :
+ begin
+ ppufile.putaint(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(200411061);
+ end;
+ end;
+
+
+{****************************************************************************
+ TTYPEDCONSTSYM
+*****************************************************************************}
+
+ constructor ttypedconstsym.create(const n : string;p : tdef;writable : boolean);
+ begin
+ inherited create(n);
+ typ:=typedconstsym;
+ typedconsttype.setdef(p);
+ is_writable:=writable;
+ end;
+
+
+ constructor ttypedconstsym.createtype(const n : string;const tt : ttype;writable : boolean);
+ begin
+ inherited create(n);
+ typ:=typedconstsym;
+ typedconsttype:=tt;
+ is_writable:=writable;
+ end;
+
+
+ constructor ttypedconstsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=typedconstsym;
+ ppufile.gettype(typedconsttype);
+ is_writable:=boolean(ppufile.getbyte);
+ end;
+
+
+ destructor ttypedconstsym.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;
+
+
+ function ttypedconstsym.mangledname:string;
+ begin
+ if not assigned(_mangledname) then
+ begin
+ {$ifdef compress}
+ _mangledname:=stringdup(make_mangledname('TC',owner,name));
+ {$else}
+ _mangledname:=stringdup(make_mangledname('TC',owner,name));
+ {$endif}
+ end;
+ result:=_mangledname^;
+ end;
+
+
+ function ttypedconstsym.getsize : longint;
+ begin
+ if assigned(typedconsttype.def) then
+ getsize:=typedconsttype.def.size
+ else
+ getsize:=0;
+ end;
+
+
+ procedure ttypedconstsym.buildderef;
+ begin
+ typedconsttype.buildderef;
+ end;
+
+
+ procedure ttypedconstsym.deref;
+ begin
+ typedconsttype.resolve;
+ end;
+
+
+ procedure ttypedconstsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(typedconsttype);
+ ppufile.putbyte(byte(is_writable));
+ ppufile.writeentry(ibtypedconstsym);
+ end;
+
+
+{****************************************************************************
+ TCONSTSYM
+****************************************************************************}
+
+ constructor tconstsym.create_ord(const n : string;t : tconsttyp;v : tconstexprint;const tt:ttype);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueord:=v;
+ ResStrIndex:=0;
+ consttype:=tt;
+ end;
+
+
+ constructor tconstsym.create_ordptr(const n : string;t : tconsttyp;v : tconstptruint;const tt:ttype);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueordptr:=v;
+ ResStrIndex:=0;
+ consttype:=tt;
+ end;
+
+
+ constructor tconstsym.create_ptr(const n : string;t : tconsttyp;v : pointer;const tt:ttype);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueptr:=v;
+ ResStrIndex:=0;
+ consttype:=tt;
+ end;
+
+
+ constructor tconstsym.create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ value.valueptr:=str;
+ consttype.reset;
+ value.len:=l;
+ if t=constresourcestring then
+ ResStrIndex:=resourcestrings.Register(name,pchar(value.valueptr),value.len);
+ end;
+
+
+ constructor tconstsym.create_wstring(const n : string;t : tconsttyp;pw:pcompilerwidestring);
+ begin
+ inherited create(n);
+ fillchar(value, sizeof(value), #0);
+ typ:=constsym;
+ consttyp:=t;
+ pcompilerwidestring(value.valueptr):=pw;
+ consttype.reset;
+ value.len:=getlengthwidestring(pw);
+ end;
+
+
+ constructor tconstsym.ppuload(ppufile:tcompilerppufile);
+ var
+ pd : pbestreal;
+ ps : pnormalset;
+ pc : pchar;
+ pw : pcompilerwidestring;
+ begin
+ inherited ppuload(ppufile);
+ typ:=constsym;
+ consttype.reset;
+ consttyp:=tconsttyp(ppufile.getbyte);
+ fillchar(value, sizeof(value), #0);
+ case consttyp of
+ constord :
+ begin
+ ppufile.gettype(consttype);
+ value.valueord:=ppufile.getexprint;
+ end;
+ constpointer :
+ begin
+ ppufile.gettype(consttype);
+ value.valueordptr:=ppufile.getptruint;
+ end;
+ constwstring :
+ begin
+ initwidestring(pw);
+ setlengthwidestring(pw,ppufile.getlongint);
+ ppufile.getdata(pw^.data,pw^.len*sizeof(tcompilerwidechar));
+ pcompilerwidestring(value.valueptr):=pw;
+ end;
+ conststring,
+ constresourcestring :
+ begin
+ value.len:=ppufile.getlongint;
+ getmem(pc,value.len+1);
+ ppufile.getdata(pc^,value.len);
+ if consttyp=constresourcestring then
+ ResStrIndex:=ppufile.getlongint;
+ value.valueptr:=pc;
+ end;
+ constreal :
+ begin
+ new(pd);
+ pd^:=ppufile.getreal;
+ value.valueptr:=pd;
+ end;
+ constset :
+ begin
+ ppufile.gettype(consttype);
+ 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
+ consttype.buildderef;
+ end;
+
+
+ procedure tconstsym.deref;
+ begin
+ if consttyp in [constord,constpointer,constset] then
+ consttype.resolve;
+ end;
+
+
+ procedure tconstsym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(consttyp));
+ case consttyp of
+ constnil : ;
+ constord :
+ begin
+ ppufile.puttype(consttype);
+ ppufile.putexprint(value.valueord);
+ end;
+ constpointer :
+ begin
+ ppufile.puttype(consttype);
+ 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);
+ if consttyp=constresourcestring then
+ ppufile.putlongint(ResStrIndex);
+ end;
+ constreal :
+ ppufile.putreal(pbestreal(value.valueptr)^);
+ constset :
+ begin
+ ppufile.puttype(consttype);
+ 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(n);
+ typ:=enumsym;
+ definition:=def;
+ value:=v;
+ { First entry? Then we need to set the minval }
+ if def.firstenum=nil then
+ begin
+ if v>0 then
+ def.has_jumps:=true;
+ def.setmin(v);
+ def.setmax(v);
+ end
+ else
+ begin
+ { check for jumps }
+ if v>def.max+1 then
+ def.has_jumps:=true;
+ { update low and high }
+ if def.min>v then
+ def.setmin(v);
+ if def.max<v then
+ def.setmax(v);
+ end;
+ order;
+ end;
+
+
+ constructor tenumsym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=enumsym;
+ ppufile.getderef(definitionderef);
+ value:=ppufile.getlongint;
+ nextenum := Nil;
+ end;
+
+
+ procedure tenumsym.buildderef;
+ begin
+ definitionderef.build(definition);
+ end;
+
+
+ procedure tenumsym.deref;
+ begin
+ definition:=tenumdef(definitionderef.resolve);
+ order;
+ end;
+
+ procedure tenumsym.order;
+ var
+ sym : tenumsym;
+ begin
+ sym := tenumsym(definition.firstenum);
+ if sym = nil then
+ begin
+ definition.firstenum := self;
+ nextenum := nil;
+ exit;
+ end;
+ { reorder the symbols in increasing value }
+ if value < sym.value then
+ begin
+ nextenum := sym;
+ definition.firstenum := self;
+ end
+ else
+ begin
+ while (sym.value <= value) and assigned(sym.nextenum) do
+ sym := sym.nextenum;
+ nextenum := sym.nextenum;
+ sym.nextenum := self;
+ end;
+ 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;const tt : ttype);
+
+ begin
+ inherited create(n);
+ typ:=typesym;
+ restype:=tt;
+ { register the typesym for the definition }
+ if assigned(restype.def) and
+ (restype.def.deftype<>errordef) and
+ not(assigned(restype.def.typesym)) then
+ restype.def.typesym:=self;
+ end;
+
+
+ constructor ttypesym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=typesym;
+ ppufile.gettype(restype);
+ end;
+
+
+ function ttypesym.gettypedef:tdef;
+ begin
+ gettypedef:=restype.def;
+ end;
+
+
+ procedure ttypesym.buildderef;
+ begin
+ restype.buildderef;
+ end;
+
+
+ procedure ttypesym.deref;
+ begin
+ restype.resolve;
+ end;
+
+
+ procedure ttypesym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.puttype(restype);
+ ppufile.writeentry(ibtypesym);
+ end;
+
+
+ procedure ttypesym.load_references(ppufile:tcompilerppufile;locals:boolean);
+ begin
+ inherited load_references(ppufile,locals);
+ if (restype.def.deftype=recorddef) then
+ tstoredsymtable(trecorddef(restype.def).symtable).load_references(ppufile,locals);
+ if (restype.def.deftype=objectdef) then
+ tstoredsymtable(tobjectdef(restype.def).symtable).load_references(ppufile,locals);
+ end;
+
+
+ function ttypesym.write_references(ppufile:tcompilerppufile;locals:boolean):boolean;
+ var
+ d : tderef;
+ begin
+ d.reset;
+ if not inherited write_references(ppufile,locals) then
+ begin
+ { write address of this symbol if record or object
+ even if no real refs are there
+ because we need it for the symtable }
+ if (restype.def.deftype in [recorddef,objectdef]) then
+ begin
+ d.build(self);
+ ppufile.putderef(d);
+ ppufile.writeentry(ibsymref);
+ end;
+ end;
+ write_references:=true;
+ if (restype.def.deftype=recorddef) then
+ tstoredsymtable(trecorddef(restype.def).symtable).write_references(ppufile,locals);
+ if (restype.def.deftype=objectdef) then
+ tstoredsymtable(tobjectdef(restype.def).symtable).write_references(ppufile,locals);
+ end;
+
+
+{****************************************************************************
+ TSYSSYM
+****************************************************************************}
+
+ constructor tsyssym.create(const n : string;l : longint);
+ begin
+ inherited create(n);
+ typ:=syssym;
+ number:=l;
+ end;
+
+ constructor tsyssym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=syssym;
+ 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(n);
+ typ:= macrosym;
+ owner:= nil;
+
+ defined:=false;
+ is_used:=false;
+ is_compiler_var:= false;
+ buftext:=nil;
+ buflen:=0;
+ end;
+
+ constructor tmacro.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=macrosym;
+ name:=ppufile.getstring;
+ 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,buflen);
+ inherited destroy;
+ end;
+
+ procedure tmacro.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putstring(name);
+ 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;
+
+
+{****************************************************************************
+ TRTTISYM
+****************************************************************************}
+
+ constructor trttisym.create(const n:string;rt:trttitype);
+ const
+ prefix : array[trttitype] of string[5]=('$rtti','$init');
+ begin
+ inherited create(prefix[rt]+n);
+ include(symoptions,sp_internal);
+ typ:=rttisym;
+ lab:=nil;
+ rttityp:=rt;
+ end;
+
+
+ destructor trttisym.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;
+
+
+ constructor trttisym.ppuload(ppufile:tcompilerppufile);
+ begin
+ inherited ppuload(ppufile);
+ typ:=rttisym;
+ lab:=nil;
+ rttityp:=trttitype(ppufile.getbyte);
+ end;
+
+
+ procedure trttisym.ppuwrite(ppufile:tcompilerppufile);
+ begin
+ inherited ppuwrite(ppufile);
+ ppufile.putbyte(byte(rttityp));
+ ppufile.writeentry(ibrttisym);
+ end;
+
+
+ function trttisym.mangledname : string;
+ const
+ prefix : array[trttitype] of string[5]=('RTTI_','INIT_');
+ begin
+ if not assigned(_mangledname) then
+ _mangledname:=stringdup(make_mangledname(prefix[rttityp],owner,Copy(name,5,255)));
+ result:=_mangledname^;
+ end;
+
+
+ function trttisym.get_label:tasmsymbol;
+ begin
+ { the label is always a global label }
+ if not assigned(lab) then
+ lab:=objectlibrary.newasmsymbol(mangledname,AB_EXTERNAL,AT_DATA);
+ get_label:=lab;
+ end;
+
+
+end.