mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-26 23:43:41 +02:00
2636 lines
78 KiB
ObjectPascal
2636 lines
78 KiB
ObjectPascal
{
|
|
$Id$
|
|
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 }
|
|
cpuinfo,
|
|
{ symtable }
|
|
symconst,symbase,symtype,symdef,
|
|
{ ppu }
|
|
ppu,symppu,
|
|
{$ifdef var_notification}
|
|
cclasses,symnot,
|
|
{$endif}
|
|
{ aasm }
|
|
aasmbase,aasmtai,cpubase,
|
|
globals
|
|
;
|
|
|
|
type
|
|
{************************************************
|
|
TSym
|
|
************************************************}
|
|
|
|
{ this object is the base for all symbol objects }
|
|
tstoredsym = class(tsym)
|
|
protected
|
|
_mangledname : pstring;
|
|
public
|
|
{$ifdef GDB}
|
|
isstabwritten : boolean;
|
|
{$endif GDB}
|
|
refs : longint;
|
|
lastref,
|
|
defref,
|
|
lastwritten : tref;
|
|
refcount : longint;
|
|
constructor create(const n : string);
|
|
constructor loadsym(ppufile:tcompilerppufile);
|
|
destructor destroy;override;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);virtual;abstract;
|
|
procedure writesym(ppufile:tcompilerppufile);
|
|
procedure deref;override;
|
|
{$ifdef GDB}
|
|
function stabstring : pchar;virtual;
|
|
procedure concatstabto(asmlist : taasmoutput);virtual;
|
|
{$endif GDB}
|
|
procedure load_references(ppufile:tcompilerppufile;locals:boolean);virtual;
|
|
function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;virtual;
|
|
function is_visible_for_proc(currprocdef:tprocdef):boolean;
|
|
function is_visible_for_object(currobjdef:tobjectdef):boolean;
|
|
function mangledname : string;
|
|
procedure generate_mangledname;virtual;abstract;
|
|
end;
|
|
|
|
tlabelsym = class(tstoredsym)
|
|
lab : tasmlabel;
|
|
used,
|
|
defined : boolean;
|
|
code : pointer; { should be tnode }
|
|
constructor create(const n : string; l : tasmlabel);
|
|
destructor destroy;override;
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
procedure generate_mangledname;override;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
end;
|
|
|
|
tunitsym = class(tstoredsym)
|
|
unitsymtable : tsymtable;
|
|
prevsym : tunitsym;
|
|
constructor create(const n : string;ref : tsymtable);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
destructor destroy;override;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
procedure restoreunitsym;
|
|
{$ifdef GDB}
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
terrorsym = class(tstoredsym)
|
|
constructor create;
|
|
end;
|
|
|
|
Tprocdefcallback = procedure(p:Tprocdef;arg:pointer);
|
|
|
|
tprocsym = class(tstoredsym)
|
|
protected
|
|
defs : pprocdeflist; { linked list of overloaded procdefs }
|
|
function getprocdef(nr:cardinal):Tprocdef;
|
|
public
|
|
procdef_count : cardinal;
|
|
is_global : boolean;
|
|
overloadchecked : boolean;
|
|
overloadcount : longint; { amount of overloaded functions in this module }
|
|
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 deref;override;
|
|
procedure addprocdef(p:tprocdef);
|
|
procedure add_para_match_to(Aprocsym:Tprocsym);
|
|
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(params:Tparalinkedlist;
|
|
allowconvert,
|
|
allowdefault:boolean):Tprocdef;
|
|
function search_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
|
|
function search_procdef_by1paradef(firstpara:Tdef):Tprocdef;
|
|
function search_procdef_byretdef_by1paradef(retdef,firstpara:Tdef;
|
|
matchtype:Tdefmatch; var pd : pprocdeflist):Tprocdef;
|
|
function write_references(ppufile:tcompilerppufile;locals:boolean):boolean;override;
|
|
{$ifdef GDB}
|
|
function stabstring : pchar;override;
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
ttypesym = class(tstoredsym)
|
|
restype : ttype;
|
|
{$ifdef GDB}
|
|
isusedinstab : boolean;
|
|
{$endif GDB}
|
|
constructor create(const n : string;const tt : ttype);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
procedure ppuwrite(ppufile:tcompilerppufile);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;
|
|
{$ifdef GDB}
|
|
function stabstring : pchar;override;
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
tvarsym = class(tstoredsym)
|
|
address : longint;
|
|
localvarsym : tvarsym;
|
|
vartype : ttype;
|
|
varoptions : tvaroptions;
|
|
reg : tregister; { if reg<>R_NO, then the variable is an register variable }
|
|
varspez : tvarspez; { sets the type of access }
|
|
varstate : tvarstate;
|
|
paraitem : tparaitem;
|
|
{$ifdef var_notification}
|
|
notifications : Tlinkedlist;
|
|
{$endif}
|
|
constructor create(const n : string;const tt : ttype);
|
|
constructor create_dll(const n : string;const tt : ttype);
|
|
constructor create_C(const n,mangled : string;const tt : ttype);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
destructor destroy;override;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
procedure deref;override;
|
|
procedure generate_mangledname;override;
|
|
procedure set_mangledname(const s:string);
|
|
function getsize : longint;
|
|
function getvaluesize : longint;
|
|
function getpushsize(is_cdecl:boolean): longint;
|
|
{$ifdef var_notification}
|
|
function register_notification(flags:Tnotification_flags;
|
|
callback:Tnotification_callback):cardinal;
|
|
{$endif}
|
|
{$ifdef GDB}
|
|
function stabstring : pchar;override;
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
tpropertysym = class(tstoredsym)
|
|
propoptions : tpropertyoptions;
|
|
propoverriden : tpropertysym;
|
|
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 deref;override;
|
|
procedure dooverride(overriden:tpropertysym);
|
|
{$ifdef GDB}
|
|
function stabstring : pchar;override;
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
tfuncretsym = class(tstoredsym)
|
|
returntype : ttype;
|
|
address : longint;
|
|
funcretstate : tvarstate;
|
|
constructor create(const n : string;const tt : ttype);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
destructor destroy;override;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
procedure deref;override;
|
|
{$ifdef GDB}
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
tabsolutesym = class(tvarsym)
|
|
abstyp : absolutetyp;
|
|
absseg : boolean;
|
|
ref : tstoredsym;
|
|
asmname : pstring;
|
|
constructor create(const n : string;const tt : ttype);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
procedure deref;override;
|
|
function mangledname : string;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
{$ifdef GDB}
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
ttypedconstsym = class(tstoredsym)
|
|
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;
|
|
procedure generate_mangledname;override;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
procedure deref;override;
|
|
function getsize:longint;
|
|
{$ifdef GDB}
|
|
function stabstring : pchar;override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
tconstsym = class(tstoredsym)
|
|
consttype : ttype;
|
|
consttyp : tconsttyp;
|
|
resstrindex, { needed for resource strings }
|
|
valueord : tconstexprint; { used for ordinal values }
|
|
valueordptr : TConstPtrUInt; { used for pointer values }
|
|
valueptr : pointer; { used for string, set, real values }
|
|
len : longint; { len is needed for string length }
|
|
constructor create_ord(const n : string;t : tconsttyp;v : tconstexprint);
|
|
constructor create_ord_typed(const n : string;t : tconsttyp;v : tconstexprint;const tt:ttype);
|
|
constructor create_ordptr_typed(const n : string;t : tconsttyp;v : tconstptruint;const tt:ttype);
|
|
constructor create_ptr(const n : string;t : tconsttyp;v : pointer);
|
|
constructor create_ptr_typed(const n : string;t : tconsttyp;v : pointer;const tt:ttype);
|
|
constructor create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
destructor destroy;override;
|
|
function mangledname : string;
|
|
procedure deref;override;
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
{$ifdef GDB}
|
|
function stabstring : pchar;override;
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
tenumsym = class(tstoredsym)
|
|
value : longint;
|
|
definition : tenumdef;
|
|
nextenum : tenumsym;
|
|
constructor create(const n : string;def : tenumdef;v : longint);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
procedure deref;override;
|
|
procedure order;
|
|
{$ifdef GDB}
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
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;
|
|
{$ifdef GDB}
|
|
procedure concatstabto(asmlist : taasmoutput);override;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
{ compiler generated symbol to point to rtti and init/finalize tables }
|
|
trttisym = class(tstoredsym)
|
|
lab : tasmsymbol;
|
|
rttityp : trttitype;
|
|
constructor create(const n:string;rt:trttitype);
|
|
constructor ppuload(ppufile:tcompilerppufile);
|
|
procedure ppuwrite(ppufile:tcompilerppufile);override;
|
|
function mangledname:string;
|
|
function get_label:tasmsymbol;
|
|
end;
|
|
|
|
{ register variables }
|
|
pregvarinfo = ^tregvarinfo;
|
|
tregvarinfo = record
|
|
regvars : array[1..maxvarregs] of tvarsym;
|
|
regvars_para : array[1..maxvarregs] of boolean;
|
|
regvars_refs : array[1..maxvarregs] of longint;
|
|
|
|
fpuregvars : array[1..maxfpuvarregs] of tvarsym;
|
|
fpuregvars_para : array[1..maxfpuvarregs] of boolean;
|
|
fpuregvars_refs : array[1..maxfpuvarregs] of longint;
|
|
end;
|
|
|
|
|
|
var
|
|
aktprocsym : tprocsym; { pointer to the symbol for the
|
|
currently be parsed procedure }
|
|
aktprocdef : tprocdef;
|
|
|
|
aktcallprocdef : tabstractprocdef; { pointer to the definition of the
|
|
currently called procedure,
|
|
only set/unset in ncal }
|
|
|
|
generrorsym : tsym;
|
|
|
|
otsym : tvarsym;
|
|
|
|
const
|
|
current_object_option : tsymoptions = [sp_public];
|
|
|
|
{ rtti and init/final }
|
|
procedure generate_rtti(p:tsym);
|
|
procedure generate_inittable(p:tsym);
|
|
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
{$ifdef Delphi}
|
|
sysutils,
|
|
{$else Delphi}
|
|
strings,
|
|
{$endif Delphi}
|
|
{ global }
|
|
globtype,verbose,
|
|
{ target }
|
|
systems,
|
|
{ symtable }
|
|
symtable,defbase,
|
|
{$ifdef GDB}
|
|
gdb,
|
|
{$endif GDB}
|
|
{ tree }
|
|
node,
|
|
{ aasm }
|
|
aasmcpu,
|
|
{ module }
|
|
fmodule,
|
|
{ codegen }
|
|
paramgr,cgbase,cresstr
|
|
;
|
|
|
|
{****************************************************************************
|
|
Helpers
|
|
****************************************************************************}
|
|
|
|
{****************************************************************************
|
|
TSYM (base for all symtypes)
|
|
****************************************************************************}
|
|
|
|
constructor tstoredsym.create(const n : string);
|
|
begin
|
|
inherited create(n);
|
|
symoptions:=current_object_option;
|
|
{$ifdef GDB}
|
|
isstabwritten := false;
|
|
{$endif GDB}
|
|
fileinfo:=akttokenpos;
|
|
defref:=nil;
|
|
refs:=0;
|
|
lastwritten:=nil;
|
|
refcount:=0;
|
|
if (cs_browser in aktmoduleswitches) and make_ref then
|
|
begin
|
|
defref:=tref.create(defref,@akttokenpos);
|
|
inc(refcount);
|
|
end;
|
|
lastref:=defref;
|
|
_mangledname:=nil;
|
|
end;
|
|
|
|
|
|
constructor tstoredsym.loadsym(ppufile:tcompilerppufile);
|
|
var
|
|
s : string;
|
|
nr : word;
|
|
begin
|
|
nr:=ppufile.getword;
|
|
s:=ppufile.getstring;
|
|
inherited create(s);
|
|
{ force the correct indexnr. must be after create! }
|
|
indexnr:=nr;
|
|
ppufile.getsmallset(symoptions);
|
|
ppufile.getposinfo(fileinfo);
|
|
lastref:=nil;
|
|
defref:=nil;
|
|
refs:=0;
|
|
lastwritten:=nil;
|
|
refcount:=0;
|
|
_mangledname:=nil;
|
|
{$ifdef GDB}
|
|
isstabwritten := false;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
|
|
procedure tstoredsym.deref;
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure tstoredsym.load_references(ppufile:tcompilerppufile;locals:boolean);
|
|
var
|
|
pos : tfileposinfo;
|
|
move_last : boolean;
|
|
begin
|
|
move_last:=lastwritten=lastref;
|
|
while (not ppufile.endofentry) do
|
|
begin
|
|
ppufile.getposinfo(pos);
|
|
inc(refcount);
|
|
lastref:=tref.create(lastref,@pos);
|
|
lastref.is_written:=true;
|
|
if refcount=1 then
|
|
defref:=lastref;
|
|
end;
|
|
if move_last then
|
|
lastwritten:=lastref;
|
|
end;
|
|
|
|
{ big problem here :
|
|
wrong refs were written because of
|
|
interface parsing of other units PM
|
|
moduleindex must be checked !! }
|
|
|
|
function tstoredsym.write_references(ppufile:tcompilerppufile;locals:boolean):boolean;
|
|
var
|
|
ref : tref;
|
|
symref_written,move_last : boolean;
|
|
begin
|
|
write_references:=false;
|
|
if lastwritten=lastref then
|
|
exit;
|
|
{ should we update lastref }
|
|
move_last:=true;
|
|
symref_written:=false;
|
|
{ write symbol refs }
|
|
if assigned(lastwritten) then
|
|
ref:=lastwritten
|
|
else
|
|
ref:=defref;
|
|
while assigned(ref) do
|
|
begin
|
|
if ref.moduleindex=current_module.unit_index then
|
|
begin
|
|
{ write address to this symbol }
|
|
if not symref_written then
|
|
begin
|
|
ppufile.putderef(self);
|
|
symref_written:=true;
|
|
end;
|
|
ppufile.putposinfo(ref.posinfo);
|
|
ref.is_written:=true;
|
|
if move_last then
|
|
lastwritten:=ref;
|
|
end
|
|
else if not ref.is_written then
|
|
move_last:=false
|
|
else if move_last then
|
|
lastwritten:=ref;
|
|
ref:=ref.nextref;
|
|
end;
|
|
if symref_written then
|
|
ppufile.writeentry(ibsymref);
|
|
write_references:=symref_written;
|
|
end;
|
|
|
|
|
|
destructor tstoredsym.destroy;
|
|
begin
|
|
if assigned(_mangledname) then
|
|
begin
|
|
{$ifdef MEMDEBUG}
|
|
memmanglednames.start;
|
|
{$endif MEMDEBUG}
|
|
stringdispose(_mangledname);
|
|
{$ifdef MEMDEBUG}
|
|
memmanglednames.stop;
|
|
{$endif MEMDEBUG}
|
|
end;
|
|
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;
|
|
|
|
|
|
procedure tstoredsym.writesym(ppufile:tcompilerppufile);
|
|
begin
|
|
ppufile.putword(indexnr);
|
|
ppufile.putstring(_realname^);
|
|
ppufile.putsmallset(symoptions);
|
|
ppufile.putposinfo(fileinfo);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tstoredsym.stabstring : pchar;
|
|
|
|
begin
|
|
stabstring:=strpnew('"'+name+'",'+tostr(N_LSYM)+',0,'+
|
|
tostr(fileinfo.line)+',0');
|
|
end;
|
|
|
|
procedure tstoredsym.concatstabto(asmlist : taasmoutput);
|
|
var
|
|
stab_str : pchar;
|
|
begin
|
|
if not isstabwritten then
|
|
begin
|
|
stab_str := stabstring;
|
|
{ count_dbx(stab_str); moved to GDB.PAS }
|
|
asmList.concat(Tai_stabs.Create(stab_str));
|
|
isstabwritten:=true;
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
function tstoredsym.is_visible_for_proc(currprocdef:tprocdef):boolean;
|
|
begin
|
|
is_visible_for_proc:=false;
|
|
|
|
{ private symbols are allowed when we are in the same
|
|
module as they are defined }
|
|
if (sp_private in symoptions) and
|
|
(owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
|
|
(owner.defowner.owner.unitid<>0) then
|
|
exit;
|
|
|
|
{ protected symbols are vissible in the module that defines them and
|
|
also visible to related objects }
|
|
if (sp_protected in symoptions) and
|
|
(
|
|
(
|
|
(owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
|
|
(owner.defowner.owner.unitid<>0)
|
|
) and
|
|
not(
|
|
assigned(currprocdef) and
|
|
assigned(currprocdef._class) and
|
|
currprocdef._class.is_related(tobjectdef(owner.defowner))
|
|
)
|
|
) then
|
|
exit;
|
|
|
|
is_visible_for_proc:=true;
|
|
end;
|
|
|
|
|
|
function tstoredsym.is_visible_for_object(currobjdef:tobjectdef):boolean;
|
|
begin
|
|
is_visible_for_object:=false;
|
|
|
|
{ private symbols are allowed when we are in the same
|
|
module as they are defined }
|
|
if (sp_private in symoptions) and
|
|
(owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
|
|
(owner.defowner.owner.unitid<>0) then
|
|
exit;
|
|
|
|
{ protected symbols are vissible in the module that defines them and
|
|
also visible to related objects }
|
|
if (sp_protected in symoptions) and
|
|
(
|
|
(
|
|
(owner.defowner.owner.symtabletype in [globalsymtable,staticsymtable]) and
|
|
(owner.defowner.owner.unitid<>0)
|
|
) and
|
|
not(
|
|
assigned(currobjdef) and
|
|
currobjdef.is_related(tobjectdef(owner.defowner))
|
|
)
|
|
) then
|
|
exit;
|
|
|
|
is_visible_for_object:=true;
|
|
end;
|
|
|
|
|
|
function tstoredsym.mangledname : string;
|
|
begin
|
|
if not assigned(_mangledname) then
|
|
begin
|
|
generate_mangledname;
|
|
if not assigned(_mangledname) then
|
|
internalerror(200204171);
|
|
end;
|
|
mangledname:=_mangledname^
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
TLABELSYM
|
|
****************************************************************************}
|
|
|
|
constructor tlabelsym.create(const n : string; l : tasmlabel);
|
|
|
|
begin
|
|
inherited create(n);
|
|
typ:=labelsym;
|
|
lab:=l;
|
|
used:=false;
|
|
defined:=false;
|
|
code:=nil;
|
|
end;
|
|
|
|
constructor tlabelsym.ppuload(ppufile:tcompilerppufile);
|
|
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
typ:=labelsym;
|
|
{ this is all dummy
|
|
it is only used for local browsing }
|
|
lab:=nil;
|
|
code:=nil;
|
|
used:=false;
|
|
defined:=true;
|
|
end;
|
|
|
|
destructor tlabelsym.destroy;
|
|
|
|
begin
|
|
inherited destroy;
|
|
end;
|
|
|
|
|
|
procedure tlabelsym.generate_mangledname;
|
|
begin
|
|
_mangledname:=stringdup(lab.name);
|
|
end;
|
|
|
|
|
|
procedure tlabelsym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
if owner.symtabletype=globalsymtable then
|
|
Message(sym_e_ill_label_decl)
|
|
else
|
|
begin
|
|
inherited writesym(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;
|
|
if assigned(ref) and
|
|
(ref.symtabletype=globalsymtable) then
|
|
begin
|
|
prevsym:=tglobalsymtable(ref).unitsym;
|
|
tglobalsymtable(ref).unitsym:=self;
|
|
end;
|
|
end;
|
|
|
|
constructor tunitsym.ppuload(ppufile:tcompilerppufile);
|
|
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
typ:=unitsym;
|
|
unitsymtable:=nil;
|
|
prevsym:=nil;
|
|
refs:=0;
|
|
end;
|
|
|
|
{ we need to remove it from the prevsym chain ! }
|
|
|
|
procedure tunitsym.restoreunitsym;
|
|
var pus,ppus : tunitsym;
|
|
begin
|
|
if assigned(unitsymtable) and
|
|
(unitsymtable.symtabletype=globalsymtable) then
|
|
begin
|
|
ppus:=nil;
|
|
pus:=tglobalsymtable(unitsymtable).unitsym;
|
|
if pus=self then
|
|
tglobalsymtable(unitsymtable).unitsym:=prevsym
|
|
else while assigned(pus) do
|
|
begin
|
|
if pus=self then
|
|
begin
|
|
ppus.prevsym:=prevsym;
|
|
break;
|
|
end
|
|
else
|
|
begin
|
|
ppus:=pus;
|
|
pus:=ppus.prevsym;
|
|
end;
|
|
end;
|
|
end;
|
|
unitsymtable:=nil;
|
|
prevsym:=nil;
|
|
end;
|
|
|
|
destructor tunitsym.destroy;
|
|
begin
|
|
restoreunitsym;
|
|
inherited destroy;
|
|
end;
|
|
|
|
procedure tunitsym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited writesym(ppufile);
|
|
ppufile.writeentry(ibunitsym);
|
|
end;
|
|
|
|
{$ifdef GDB}
|
|
procedure tunitsym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
{Nothing to write to stabs !}
|
|
end;
|
|
{$endif GDB}
|
|
|
|
{****************************************************************************
|
|
TPROCSYM
|
|
****************************************************************************}
|
|
|
|
constructor tprocsym.create(const n : string);
|
|
|
|
begin
|
|
inherited create(n);
|
|
typ:=procsym;
|
|
defs:=nil;
|
|
owner:=nil;
|
|
is_global:=false;
|
|
overloadchecked:=false;
|
|
overloadcount:=0;
|
|
procdef_count:=0;
|
|
end;
|
|
|
|
|
|
constructor tprocsym.ppuload(ppufile:tcompilerppufile);
|
|
var
|
|
pd : tprocdef;
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
typ:=procsym;
|
|
defs:=nil;
|
|
procdef_count:=0;
|
|
repeat
|
|
pd:=tprocdef(ppufile.getderef);
|
|
if pd=nil then
|
|
break;
|
|
addprocdef(pd);
|
|
until false;
|
|
is_global:=false;
|
|
overloadchecked:=false;
|
|
overloadcount:=-1; { invalid, not used anymore }
|
|
end;
|
|
|
|
|
|
destructor tprocsym.destroy;
|
|
var
|
|
hp,p : pprocdeflist;
|
|
begin
|
|
p:=defs;
|
|
while assigned(p) do
|
|
begin
|
|
hp:=p^.next;
|
|
dispose(p);
|
|
p:=hp;
|
|
end;
|
|
inherited destroy;
|
|
end;
|
|
|
|
|
|
procedure tprocsym.write_parameter_lists(skipdef:tprocdef);
|
|
var
|
|
p : pprocdeflist;
|
|
begin
|
|
p:=defs;
|
|
while assigned(p) do
|
|
begin
|
|
if p^.def<>skipdef then
|
|
MessagePos1(p^.def.fileinfo,sym_b_param_list,p^.def.fullprocname);
|
|
p:=p^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tprocsym.check_forward;
|
|
var
|
|
p : pprocdeflist;
|
|
begin
|
|
p:=defs;
|
|
while assigned(p) do
|
|
begin
|
|
if (p^.def.procsym=self) and
|
|
(p^.def.forwarddef) then
|
|
begin
|
|
MessagePos1(p^.def.fileinfo,sym_e_forward_not_resolved,p^.def.fullprocname);
|
|
{ Turn futher error messages off }
|
|
p^.def.forwarddef:=false;
|
|
end;
|
|
p:=p^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tprocsym.deref;
|
|
var
|
|
p : pprocdeflist;
|
|
begin
|
|
p:=defs;
|
|
while assigned(p) do
|
|
begin
|
|
resolvedef(pointer(p^.def));
|
|
p:=p^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tprocsym.addprocdef(p:tprocdef);
|
|
var
|
|
pd : pprocdeflist;
|
|
begin
|
|
new(pd);
|
|
pd^.def:=p;
|
|
pd^.next:=defs;
|
|
defs:=pd;
|
|
inc(procdef_count);
|
|
end;
|
|
|
|
|
|
function Tprocsym.getprocdef(nr:cardinal):Tprocdef;
|
|
var
|
|
i : cardinal;
|
|
pd : Pprocdeflist;
|
|
begin
|
|
pd:=defs;
|
|
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);
|
|
var
|
|
pd:Pprocdeflist;
|
|
begin
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
if Aprocsym.search_procdef_bypara(pd^.def.para,false,true)=nil then
|
|
Aprocsym.addprocdef(pd^.def);
|
|
pd:=pd^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure Tprocsym.concat_procdefs_to(s:Tprocsym);
|
|
|
|
var pd:Pprocdeflist;
|
|
|
|
begin
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
s.addprocdef(pd^.def);
|
|
pd:=pd^.next;
|
|
end;
|
|
end;
|
|
|
|
function Tprocsym.first_procdef:Tprocdef;
|
|
|
|
begin
|
|
first_procdef:=defs^.def;
|
|
end;
|
|
|
|
function Tprocsym.last_procdef:Tprocdef;
|
|
|
|
var pd:Pprocdeflist;
|
|
|
|
begin
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
last_procdef:=pd^.def;
|
|
pd:=pd^.next;
|
|
end;
|
|
end;
|
|
|
|
procedure Tprocsym.foreach_procdef_static(proc2call:Tprocdefcallback;arg:pointer);
|
|
|
|
var p:Pprocdeflist;
|
|
|
|
begin
|
|
p:=defs;
|
|
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:=defs;
|
|
while p<>nil do
|
|
begin
|
|
if p^.def.para.empty 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:=defs;
|
|
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(params:Tparalinkedlist;
|
|
allowconvert,
|
|
allowdefault:boolean):Tprocdef;
|
|
|
|
var
|
|
pd:Pprocdeflist;
|
|
begin
|
|
search_procdef_bypara:=nil;
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
if equal_paras(pd^.def.para,params,cp_value_equal_const,allowdefault) or
|
|
(allowconvert and convertable_paras(pd^.def.para,params,
|
|
cp_value_equal_const)) then
|
|
begin
|
|
search_procdef_bypara:=pd^.def;
|
|
break;
|
|
end;
|
|
pd:=pd^.next;
|
|
end;
|
|
end;
|
|
|
|
function Tprocsym.search_procdef_byprocvardef(d:Tprocvardef):Tprocdef;
|
|
var pd:Pprocdeflist;
|
|
_result : 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.}
|
|
{Try to find an exact match first.}
|
|
search_procdef_byprocvardef:=nil;
|
|
_result := nil;
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
if proc_to_procvar_equal(pd^.def,d,true) then
|
|
begin
|
|
{ already found a match ? Then stop and return nil }
|
|
if assigned(search_procdef_byprocvardef) then
|
|
begin
|
|
search_procdef_byprocvardef:=nil;
|
|
break;
|
|
end;
|
|
search_procdef_byprocvardef:=pd^.def;
|
|
end;
|
|
pd:=pd^.next;
|
|
end;
|
|
{Try a convertable match, if no exact match was found.}
|
|
if not assigned(_result) and not assigned(pd) then
|
|
begin
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
if proc_to_procvar_equal(pd^.def,d,false) then
|
|
begin
|
|
{ already found a match ? Then stop and return nil }
|
|
if assigned(_result) then
|
|
begin
|
|
search_procdef_byprocvardef:=nil;
|
|
_result := nil;
|
|
break;
|
|
end;
|
|
search_procdef_byprocvardef:=pd^.def;
|
|
_result:=pd^.def;
|
|
end;
|
|
pd:=pd^.next;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function Tprocsym.search_procdef_by1paradef(firstpara:Tdef):Tprocdef;
|
|
var
|
|
pd:Pprocdeflist;
|
|
begin
|
|
search_procdef_by1paradef:=nil;
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
if is_equal(Tparaitem(pd^.def.para.first).paratype.def,firstpara) and
|
|
(Tparaitem(pd^.def.para.first).next=nil) then
|
|
begin
|
|
search_procdef_by1paradef:=pd^.def;
|
|
break;
|
|
end;
|
|
pd:=pd^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
function Tprocsym.search_procdef_byretdef_by1paradef(retdef,firstpara:Tdef;
|
|
matchtype:Tdefmatch; var pd : pprocdeflist):Tprocdef;
|
|
|
|
var
|
|
convtyp:tconverttype;
|
|
a,b:boolean;
|
|
oldpd : pprocdeflist;
|
|
begin
|
|
search_procdef_byretdef_by1paradef:=nil;
|
|
if not assigned(pd) then
|
|
pd:=defs;
|
|
while assigned(pd) do
|
|
begin
|
|
oldpd := pd;
|
|
a:=is_equal(retdef,pd^.def.rettype.def);
|
|
if a then
|
|
begin
|
|
case matchtype of
|
|
dm_exact:
|
|
b:=TParaItem(pd^.def.para.first).paratype.def=firstpara;
|
|
dm_equal:
|
|
b:=is_equal(Tparaitem(pd^.def.para.first).paratype.def,firstpara);
|
|
dm_convertl1:
|
|
b:=overloaded_assignment_isconvertable(firstpara,Tparaitem(pd^.def.para.first).paratype.def,
|
|
convtyp,ordconstn,false,oldpd)=1;
|
|
end;
|
|
end;
|
|
if a and b then
|
|
begin
|
|
search_procdef_byretdef_by1paradef:=pd^.def;
|
|
break;
|
|
end;
|
|
pd:=pd^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tprocsym.ppuwrite(ppufile:tcompilerppufile);
|
|
var
|
|
p : pprocdeflist;
|
|
begin
|
|
inherited writesym(ppufile);
|
|
p:=defs;
|
|
while assigned(p) do
|
|
begin
|
|
{ only write the proc definitions that belong
|
|
to this procsym }
|
|
if (p^.def.procsym=self) then
|
|
ppufile.putderef(p^.def);
|
|
p:=p^.next;
|
|
end;
|
|
ppufile.putderef(nil);
|
|
ppufile.writeentry(ibprocsym);
|
|
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:=defs;
|
|
while assigned(p) do
|
|
begin
|
|
if (p^.def.procsym=self) then
|
|
p^.def.write_references(ppufile,locals);
|
|
p:=p^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tprocsym.unchain_overload;
|
|
var
|
|
p,hp,
|
|
first,
|
|
last : pprocdeflist;
|
|
begin
|
|
{ remove all overloaded procdefs from the
|
|
procdeflist that are not in the current symtable }
|
|
first:=nil;
|
|
last:=nil;
|
|
p:=defs;
|
|
while assigned(p) do
|
|
begin
|
|
hp:=p^.next;
|
|
if (p^.def.procsym=self) then
|
|
begin
|
|
{ keep in list }
|
|
if not assigned(first) then
|
|
begin
|
|
first:=p;
|
|
last:=p;
|
|
end
|
|
else
|
|
last^.next:=p;
|
|
last:=p;
|
|
p^.next:=nil;
|
|
end
|
|
else
|
|
begin
|
|
{ remove }
|
|
dispose(p);
|
|
dec(procdef_count);
|
|
end;
|
|
p:=hp;
|
|
end;
|
|
defs:=first;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tprocsym.stabstring : pchar;
|
|
begin
|
|
internalerror(200111171);
|
|
stabstring:=nil;
|
|
end;
|
|
|
|
procedure tprocsym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
internalerror(200111172);
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
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 loadsym(ppufile);
|
|
typ:=propertysym;
|
|
ppufile.getsmallset(propoptions);
|
|
if (ppo_is_override in propoptions) then
|
|
begin
|
|
propoverriden:=tpropertysym(ppufile.getderef);
|
|
{ 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.deref;
|
|
begin
|
|
if (ppo_is_override in propoptions) then
|
|
begin
|
|
resolvesym(pointer(propoverriden));
|
|
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 writesym(ppufile);
|
|
ppufile.putsmallset(propoptions);
|
|
if (ppo_is_override in propoptions) then
|
|
ppufile.putderef(propoverriden)
|
|
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;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tpropertysym.stabstring : pchar;
|
|
begin
|
|
{ !!!! don't know how to handle }
|
|
stabstring:=strpnew('');
|
|
end;
|
|
|
|
procedure tpropertysym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
{ !!!! don't know how to handle }
|
|
end;
|
|
{$endif GDB}
|
|
|
|
{****************************************************************************
|
|
TFUNCRETSYM
|
|
****************************************************************************}
|
|
|
|
constructor tfuncretsym.create(const n : string;const tt:ttype);
|
|
|
|
begin
|
|
inherited create(n);
|
|
typ:=funcretsym;
|
|
returntype:=tt;
|
|
funcretstate:=vs_declared;
|
|
{ address valid for ret in param only }
|
|
{ otherwise set by insert }
|
|
address:=procinfo.return_offset;
|
|
end;
|
|
|
|
constructor tfuncretsym.ppuload(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
ppufile.gettype(returntype);
|
|
address:=ppufile.getlongint;
|
|
typ:=funcretsym;
|
|
end;
|
|
|
|
destructor tfuncretsym.destroy;
|
|
begin
|
|
inherited destroy;
|
|
end;
|
|
|
|
procedure tfuncretsym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited writesym(ppufile);
|
|
ppufile.puttype(returntype);
|
|
ppufile.putlongint(address);
|
|
ppufile.writeentry(ibfuncretsym);
|
|
funcretstate:=vs_used;
|
|
end;
|
|
|
|
procedure tfuncretsym.deref;
|
|
begin
|
|
returntype.resolve;
|
|
end;
|
|
|
|
{$ifdef GDB}
|
|
procedure tfuncretsym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
{ Nothing to do here, it is done in genexitcode }
|
|
end;
|
|
{$endif GDB}
|
|
|
|
{****************************************************************************
|
|
TABSOLUTESYM
|
|
****************************************************************************}
|
|
|
|
constructor tabsolutesym.create(const n : string;const tt : ttype);
|
|
begin
|
|
inherited create(n,tt);
|
|
typ:=absolutesym;
|
|
end;
|
|
|
|
|
|
constructor tabsolutesym.ppuload(ppufile:tcompilerppufile);
|
|
begin
|
|
{ Note: This needs to load everything of tvarsym.write }
|
|
inherited ppuload(ppufile);
|
|
{ load absolute }
|
|
typ:=absolutesym;
|
|
ref:=nil;
|
|
address:=0;
|
|
asmname:=nil;
|
|
abstyp:=absolutetyp(ppufile.getbyte);
|
|
absseg:=false;
|
|
case abstyp of
|
|
tovar :
|
|
asmname:=stringdup(ppufile.getstring);
|
|
toasm :
|
|
asmname:=stringdup(ppufile.getstring);
|
|
toaddr :
|
|
begin
|
|
address:=ppufile.getlongint;
|
|
absseg:=boolean(ppufile.getbyte);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tabsolutesym.ppuwrite(ppufile:tcompilerppufile);
|
|
var
|
|
hvo : tvaroptions;
|
|
begin
|
|
{ Note: This needs to write everything of tvarsym.write }
|
|
inherited writesym(ppufile);
|
|
ppufile.putbyte(byte(varspez));
|
|
ppufile.putlongint(address);
|
|
{ write only definition or definitionsym }
|
|
ppufile.puttype(vartype);
|
|
hvo:=varoptions-[vo_regable];
|
|
ppufile.putsmallset(hvo);
|
|
ppufile.putbyte(byte(abstyp));
|
|
case abstyp of
|
|
tovar :
|
|
ppufile.putstring(ref.name);
|
|
toasm :
|
|
ppufile.putstring(asmname^);
|
|
toaddr :
|
|
begin
|
|
ppufile.putlongint(address);
|
|
ppufile.putbyte(byte(absseg));
|
|
end;
|
|
end;
|
|
ppufile.writeentry(ibabsolutesym);
|
|
end;
|
|
|
|
|
|
procedure tabsolutesym.deref;
|
|
var
|
|
srsym : tsym;
|
|
srsymtable : tsymtable;
|
|
begin
|
|
{ inheritance of varsym.deref ! }
|
|
vartype.resolve;
|
|
{ own absolute deref }
|
|
if (abstyp=tovar) and (asmname<>nil) then
|
|
begin
|
|
{ search previous loaded symtables }
|
|
searchsym(asmname^,srsym,srsymtable);
|
|
if not assigned(srsym) then
|
|
srsym:=searchsymonlyin(owner,asmname^);
|
|
if not assigned(srsym) then
|
|
srsym:=generrorsym;
|
|
ref:=tstoredsym(srsym);
|
|
stringdispose(asmname);
|
|
end;
|
|
end;
|
|
|
|
|
|
function tabsolutesym.mangledname : string;
|
|
begin
|
|
case abstyp of
|
|
tovar :
|
|
begin
|
|
case ref.typ of
|
|
varsym :
|
|
mangledname:=tvarsym(ref).mangledname;
|
|
else
|
|
internalerror(200111011);
|
|
end;
|
|
end;
|
|
toasm :
|
|
mangledname:=asmname^;
|
|
toaddr :
|
|
mangledname:='$'+tostr(address);
|
|
else
|
|
internalerror(10002);
|
|
end;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
procedure tabsolutesym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
{ I don't know how to handle this !! }
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
TVARSYM
|
|
****************************************************************************}
|
|
|
|
constructor tvarsym.create(const n : string;const tt : ttype);
|
|
begin
|
|
inherited create(n);
|
|
typ:=varsym;
|
|
vartype:=tt;
|
|
_mangledname:=nil;
|
|
varspez:=vs_value;
|
|
address:=0;
|
|
localvarsym:=nil;
|
|
refs:=0;
|
|
varstate:=vs_used;
|
|
varoptions:=[];
|
|
{ can we load the value into a register ? }
|
|
if tstoreddef(tt.def).is_intregable then
|
|
include(varoptions,vo_regable)
|
|
else
|
|
exclude(varoptions,vo_regable);
|
|
|
|
if tstoreddef(tt.def).is_fpuregable then
|
|
include(varoptions,vo_fpuregable)
|
|
else
|
|
exclude(varoptions,vo_fpuregable);
|
|
reg:=R_NO;
|
|
end;
|
|
|
|
|
|
constructor tvarsym.create_dll(const n : string;const tt : ttype);
|
|
begin
|
|
tvarsym(self).create(n,tt);
|
|
include(varoptions,vo_is_dll_var);
|
|
end;
|
|
|
|
|
|
constructor tvarsym.create_C(const n,mangled : string;const tt : ttype);
|
|
begin
|
|
tvarsym(self).create(n,tt);
|
|
stringdispose(_mangledname);
|
|
_mangledname:=stringdup(mangled);
|
|
end;
|
|
|
|
|
|
constructor tvarsym.ppuload(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
typ:=varsym;
|
|
reg:=R_NO;
|
|
refs := 0;
|
|
varstate:=vs_used;
|
|
varspez:=tvarspez(ppufile.getbyte);
|
|
address:=ppufile.getlongint;
|
|
localvarsym:=nil;
|
|
ppufile.gettype(vartype);
|
|
ppufile.getsmallset(varoptions);
|
|
if (vo_is_C_var in varoptions) then
|
|
_mangledname:=stringdup(ppufile.getstring);
|
|
end;
|
|
|
|
|
|
destructor tvarsym.destroy;
|
|
begin
|
|
{$ifdef var_notification}
|
|
if assigned(notifications) then
|
|
notifications.destroy;
|
|
{$endif}
|
|
inherited destroy;
|
|
end;
|
|
|
|
|
|
procedure tvarsym.deref;
|
|
begin
|
|
vartype.resolve;
|
|
end;
|
|
|
|
|
|
procedure tvarsym.ppuwrite(ppufile:tcompilerppufile);
|
|
var
|
|
hvo : tvaroptions;
|
|
begin
|
|
inherited writesym(ppufile);
|
|
ppufile.putbyte(byte(varspez));
|
|
ppufile.putlongint(address);
|
|
ppufile.puttype(vartype);
|
|
{ symbols which are load are never candidates for a register,
|
|
turn off the regable }
|
|
hvo:=varoptions-[vo_regable,vo_fpuregable];
|
|
ppufile.putsmallset(hvo);
|
|
if (vo_is_C_var in varoptions) then
|
|
ppufile.putstring(mangledname);
|
|
ppufile.writeentry(ibvarsym);
|
|
end;
|
|
|
|
|
|
procedure tvarsym.generate_mangledname;
|
|
begin
|
|
_mangledname:=stringdup(mangledname_prefix('U',owner)+name);
|
|
end;
|
|
|
|
|
|
procedure tvarsym.set_mangledname(const s:string);
|
|
begin
|
|
stringdispose(_mangledname);
|
|
_mangledname:=stringdup(s);
|
|
end;
|
|
|
|
|
|
function tvarsym.getsize : longint;
|
|
begin
|
|
if assigned(vartype.def) then
|
|
getsize:=vartype.def.size
|
|
else
|
|
getsize:=0;
|
|
end;
|
|
|
|
|
|
function tvarsym.getvaluesize : longint;
|
|
begin
|
|
if assigned(vartype.def) and
|
|
(varspez=vs_value) and
|
|
((vartype.def.deftype<>arraydef) or
|
|
tarraydef(vartype.def).isDynamicArray or
|
|
(tarraydef(vartype.def).highrange>=tarraydef(vartype.def).lowrange)) then
|
|
getvaluesize:=vartype.def.size
|
|
else
|
|
getvaluesize:=0;
|
|
end;
|
|
|
|
|
|
function tvarsym.getpushsize(is_cdecl:boolean) : longint;
|
|
begin
|
|
getpushsize:=-1;
|
|
if assigned(vartype.def) then
|
|
begin
|
|
case varspez of
|
|
vs_out,
|
|
vs_var :
|
|
getpushsize:=pointer_size;
|
|
vs_value,
|
|
vs_const :
|
|
begin
|
|
if paramanager.push_addr_param(vartype.def,is_cdecl) then
|
|
getpushsize:=pointer_size
|
|
else
|
|
getpushsize:=vartype.def.size;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{$ifdef var_notification}
|
|
function Tvarsym.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;
|
|
{$endif}
|
|
|
|
{$ifdef GDB}
|
|
function tvarsym.stabstring : pchar;
|
|
var
|
|
st : string;
|
|
is_cdecl : boolean;
|
|
begin
|
|
st:=tstoreddef(vartype.def).numberstring;
|
|
if (owner.symtabletype = objectsymtable) and
|
|
(sp_static in symoptions) then
|
|
begin
|
|
if (cs_gdb_gsym in aktglobalswitches) then st := 'G'+st else st := 'S'+st;
|
|
stabstring := strpnew('"'+upper(owner.name^)+'__'+name+':'+st+
|
|
'",'+
|
|
tostr(N_LCSYM)+',0,'+tostr(fileinfo.line)+','+mangledname);
|
|
end
|
|
else if (owner.symtabletype = globalsymtable) then
|
|
begin
|
|
{ Here we used S instead of
|
|
because with G GDB doesn't look at the address field
|
|
but searches the same name or with a leading underscore
|
|
but these names don't exist in pascal !}
|
|
if (cs_gdb_gsym in aktglobalswitches) then st := 'G'+st else st := 'S'+st;
|
|
stabstring := strpnew('"'+name+':'+st+'",'+
|
|
tostr(N_LCSYM)+',0,'+tostr(fileinfo.line)+','+mangledname);
|
|
end
|
|
else if owner.symtabletype = staticsymtable then
|
|
begin
|
|
stabstring := strpnew('"'+name+':S'+st+'",'+
|
|
tostr(N_LCSYM)+',0,'+tostr(fileinfo.line)+','+mangledname);
|
|
end
|
|
else if (owner.symtabletype in [parasymtable,inlineparasymtable]) then
|
|
begin
|
|
is_cdecl:=(tprocdef(owner.defowner).proccalloption in [pocall_cdecl,pocall_cppdecl]);
|
|
case varspez of
|
|
vs_out,
|
|
vs_var : st := 'v'+st;
|
|
vs_value,
|
|
vs_const : if paramanager.push_addr_param(vartype.def,is_cdecl) then
|
|
st := 'v'+st { should be 'i' but 'i' doesn't work }
|
|
else
|
|
st := 'p'+st;
|
|
end;
|
|
stabstring := strpnew('"'+name+':'+st+'",'+
|
|
tostr(N_tsym)+',0,'+tostr(fileinfo.line)+','+
|
|
tostr(address+owner.address_fixup));
|
|
{offset to ebp => will not work if the framepointer is esp
|
|
so some optimizing will make things harder to debug }
|
|
end
|
|
else if (owner.symtabletype in [localsymtable,inlinelocalsymtable]) then
|
|
if reg<>R_NO then
|
|
begin
|
|
{ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
|
|
{ this is the register order for GDB}
|
|
stabstring:=strpnew('"'+name+':r'+st+'",'+
|
|
tostr(N_RSYM)+',0,'+
|
|
tostr(fileinfo.line)+','+tostr(stab_regindex[reg]));
|
|
end
|
|
else
|
|
{ I don't know if this will work (PM) }
|
|
if (vo_is_C_var in varoptions) then
|
|
stabstring := strpnew('"'+name+':S'+st+'",'+
|
|
tostr(N_LCSYM)+',0,'+tostr(fileinfo.line)+','+mangledname)
|
|
else
|
|
stabstring := strpnew('"'+name+':'+st+'",'+
|
|
tostr(N_LSYM)+',0,'+tostr(fileinfo.line)+',-'+tostr(address-owner.address_fixup))
|
|
else
|
|
stabstring := inherited stabstring;
|
|
end;
|
|
|
|
procedure tvarsym.concatstabto(asmlist : taasmoutput);
|
|
var stab_str : pchar;
|
|
begin
|
|
inherited concatstabto(asmlist);
|
|
if (owner.symtabletype=parasymtable) and
|
|
(reg<>R_NO) then
|
|
begin
|
|
{ "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "eip", "ps", "cs", "ss", "ds", "es", "fs", "gs", }
|
|
{ this is the register order for GDB}
|
|
stab_str:=strpnew('"'+name+':r'
|
|
+tstoreddef(vartype.def).numberstring+'",'+
|
|
tostr(N_RSYM)+',0,'+
|
|
tostr(fileinfo.line)+','+tostr(stab_regindex[reg]));
|
|
asmList.concat(Tai_stabs.Create(stab_str));
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
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 loadsym(ppufile);
|
|
typ:=typedconstsym;
|
|
ppufile.gettype(typedconsttype);
|
|
is_writable:=boolean(ppufile.getbyte);
|
|
end;
|
|
|
|
|
|
destructor ttypedconstsym.destroy;
|
|
begin
|
|
inherited destroy;
|
|
end;
|
|
|
|
|
|
procedure ttypedconstsym.generate_mangledname;
|
|
begin
|
|
_mangledname:=stringdup(mangledname_prefix('TC',owner)+name);
|
|
end;
|
|
|
|
|
|
function ttypedconstsym.getsize : longint;
|
|
begin
|
|
if assigned(typedconsttype.def) then
|
|
getsize:=typedconsttype.def.size
|
|
else
|
|
getsize:=0;
|
|
end;
|
|
|
|
|
|
procedure ttypedconstsym.deref;
|
|
begin
|
|
typedconsttype.resolve;
|
|
end;
|
|
|
|
|
|
procedure ttypedconstsym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited writesym(ppufile);
|
|
ppufile.puttype(typedconsttype);
|
|
ppufile.putbyte(byte(is_writable));
|
|
ppufile.writeentry(ibtypedconstsym);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function ttypedconstsym.stabstring : pchar;
|
|
var
|
|
st : char;
|
|
begin
|
|
if (cs_gdb_gsym in aktglobalswitches) and (owner.symtabletype=globalsymtable) then
|
|
st := 'G'
|
|
else
|
|
st := 'S';
|
|
stabstring := strpnew('"'+name+':'+st+
|
|
tstoreddef(typedconsttype.def).numberstring+'",'+tostr(n_STSYM)+',0,'+
|
|
tostr(fileinfo.line)+','+mangledname);
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
TCONSTSYM
|
|
****************************************************************************}
|
|
|
|
constructor tconstsym.create_ord(const n : string;t : tconsttyp;v : TConstExprInt);
|
|
begin
|
|
inherited create(n);
|
|
typ:=constsym;
|
|
consttyp:=t;
|
|
valueord:=v;
|
|
valueordptr:=0;
|
|
valueptr:=nil;
|
|
ResStrIndex:=0;
|
|
consttype.reset;
|
|
len:=0;
|
|
end;
|
|
|
|
|
|
constructor tconstsym.create_ord_typed(const n : string;t : tconsttyp;v : tconstexprint;const tt:ttype);
|
|
begin
|
|
inherited create(n);
|
|
typ:=constsym;
|
|
consttyp:=t;
|
|
valueord:=v;
|
|
valueordptr:=0;
|
|
valueptr:=nil;
|
|
ResStrIndex:=0;
|
|
consttype:=tt;
|
|
len:=0;
|
|
end;
|
|
|
|
|
|
constructor tconstsym.create_ordptr_typed(const n : string;t : tconsttyp;v : tconstptruint;const tt:ttype);
|
|
begin
|
|
inherited create(n);
|
|
typ:=constsym;
|
|
consttyp:=t;
|
|
valueord:=0;
|
|
valueordptr:=v;
|
|
valueptr:=nil;
|
|
ResStrIndex:=0;
|
|
consttype:=tt;
|
|
len:=0;
|
|
end;
|
|
|
|
|
|
constructor tconstsym.create_ptr(const n : string;t : tconsttyp;v : pointer);
|
|
begin
|
|
inherited create(n);
|
|
typ:=constsym;
|
|
consttyp:=t;
|
|
valueord:=0;
|
|
valueordptr:=0;
|
|
valueptr:=v;
|
|
ResStrIndex:=0;
|
|
consttype.reset;
|
|
len:=0;
|
|
end;
|
|
|
|
|
|
constructor tconstsym.create_ptr_typed(const n : string;t : tconsttyp;v : pointer;const tt:ttype);
|
|
begin
|
|
inherited create(n);
|
|
typ:=constsym;
|
|
consttyp:=t;
|
|
valueord:=0;
|
|
valueordptr:=0;
|
|
valueptr:=v;
|
|
ResStrIndex:=0;
|
|
consttype:=tt;
|
|
len:=0;
|
|
end;
|
|
|
|
|
|
constructor tconstsym.create_string(const n : string;t : tconsttyp;str:pchar;l:longint);
|
|
begin
|
|
inherited create(n);
|
|
typ:=constsym;
|
|
consttyp:=t;
|
|
valueord:=0;
|
|
valueordptr:=0;
|
|
valueptr:=str;
|
|
consttype.reset;
|
|
len:=l;
|
|
if t=constresourcestring then
|
|
ResStrIndex:=ResourceStrings.Register(name,pchar(valueptr),len);
|
|
end;
|
|
|
|
|
|
constructor tconstsym.ppuload(ppufile:tcompilerppufile);
|
|
var
|
|
pd : pbestreal;
|
|
ps : pnormalset;
|
|
pc : pchar;
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
typ:=constsym;
|
|
consttype.reset;
|
|
consttyp:=tconsttyp(ppufile.getbyte);
|
|
valueord:=0;
|
|
valueordptr:=0;
|
|
valueptr:=nil;
|
|
case consttyp of
|
|
constint:
|
|
valueord:=ppufile.getexprint;
|
|
constwchar,
|
|
constbool,
|
|
constchar :
|
|
valueord:=ppufile.getlongint;
|
|
constord :
|
|
begin
|
|
ppufile.gettype(consttype);
|
|
valueord:=ppufile.getexprint;
|
|
end;
|
|
constpointer :
|
|
begin
|
|
ppufile.gettype(consttype);
|
|
valueordptr:=ppufile.getptruint;
|
|
end;
|
|
conststring,
|
|
constresourcestring :
|
|
begin
|
|
len:=ppufile.getlongint;
|
|
getmem(pc,len+1);
|
|
ppufile.getdata(pc^,len);
|
|
if consttyp=constresourcestring then
|
|
ResStrIndex:=ppufile.getlongint;
|
|
valueptr:=pc;
|
|
end;
|
|
constreal :
|
|
begin
|
|
new(pd);
|
|
pd^:=ppufile.getreal;
|
|
valueptr:=pd;
|
|
end;
|
|
constset :
|
|
begin
|
|
ppufile.gettype(consttype);
|
|
new(ps);
|
|
ppufile.getnormalset(ps^);
|
|
valueptr:=ps;
|
|
end;
|
|
constguid :
|
|
begin
|
|
new(pguid(valueptr));
|
|
ppufile.getdata(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(valueptr),len+1);
|
|
constreal :
|
|
dispose(pbestreal(valueptr));
|
|
constset :
|
|
dispose(pnormalset(valueptr));
|
|
constguid :
|
|
dispose(pguid(valueptr));
|
|
end;
|
|
inherited destroy;
|
|
end;
|
|
|
|
|
|
function tconstsym.mangledname : string;
|
|
begin
|
|
mangledname:=name;
|
|
end;
|
|
|
|
|
|
procedure tconstsym.deref;
|
|
begin
|
|
if consttyp in [constord,constpointer,constset] then
|
|
consttype.resolve;
|
|
end;
|
|
|
|
|
|
procedure tconstsym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited writesym(ppufile);
|
|
ppufile.putbyte(byte(consttyp));
|
|
case consttyp of
|
|
constnil : ;
|
|
constint:
|
|
ppufile.putexprint(valueord);
|
|
constbool,
|
|
constchar :
|
|
ppufile.putlongint(valueord);
|
|
constord :
|
|
begin
|
|
ppufile.puttype(consttype);
|
|
ppufile.putexprint(valueord);
|
|
end;
|
|
constpointer :
|
|
begin
|
|
ppufile.puttype(consttype);
|
|
ppufile.putptruint(valueordptr);
|
|
end;
|
|
conststring,
|
|
constresourcestring :
|
|
begin
|
|
ppufile.putlongint(len);
|
|
ppufile.putdata(pchar(valueptr)^,len);
|
|
if consttyp=constresourcestring then
|
|
ppufile.putlongint(ResStrIndex);
|
|
end;
|
|
constreal :
|
|
ppufile.putreal(pbestreal(valueptr)^);
|
|
constset :
|
|
begin
|
|
ppufile.puttype(consttype);
|
|
ppufile.putnormalset(valueptr^);
|
|
end;
|
|
constguid :
|
|
ppufile.putdata(valueptr^,sizeof(tguid));
|
|
else
|
|
internalerror(13);
|
|
end;
|
|
ppufile.writeentry(ibconstsym);
|
|
end;
|
|
|
|
{$ifdef GDB}
|
|
function tconstsym.stabstring : pchar;
|
|
var st : string;
|
|
begin
|
|
{even GDB v4.16 only now 'i' 'r' and 'e' !!!}
|
|
case consttyp of
|
|
conststring : begin
|
|
st := 's'''+strpas(pchar(valueptr))+'''';
|
|
end;
|
|
constbool,
|
|
constint,
|
|
constord,
|
|
constchar : st := 'i'+int64tostr(valueord);
|
|
constpointer :
|
|
st := 'i'+int64tostr(valueordptr);
|
|
constreal : begin
|
|
system.str(pbestreal(valueptr)^,st);
|
|
st := 'r'+st;
|
|
end;
|
|
{ if we don't know just put zero !! }
|
|
else st:='i0';
|
|
{***SETCONST}
|
|
{constset:;} {*** I don't know what to do with a set.}
|
|
{ sets are not recognized by GDB}
|
|
{***}
|
|
end;
|
|
stabstring := strpnew('"'+name+':c='+st+'",'+tostr(N_function)+',0,'+
|
|
tostr(fileinfo.line)+',0');
|
|
end;
|
|
|
|
procedure tconstsym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
if consttyp <> conststring then
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
TENUMSYM
|
|
****************************************************************************}
|
|
|
|
constructor tenumsym.create(const n : string;def : tenumdef;v : longint);
|
|
begin
|
|
inherited create(n);
|
|
typ:=enumsym;
|
|
definition:=def;
|
|
value:=v;
|
|
{ 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);
|
|
order;
|
|
end;
|
|
|
|
|
|
constructor tenumsym.ppuload(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
typ:=enumsym;
|
|
definition:=tenumdef(ppufile.getderef);
|
|
value:=ppufile.getlongint;
|
|
nextenum := Nil;
|
|
end;
|
|
|
|
|
|
procedure tenumsym.deref;
|
|
begin
|
|
resolvedef(pointer(definition));
|
|
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 writesym(ppufile);
|
|
ppufile.putderef(definition);
|
|
ppufile.putlongint(value);
|
|
ppufile.writeentry(ibenumsym);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
procedure tenumsym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
{enum elements have no stab !}
|
|
end;
|
|
{$EndIf GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
TTYPESYM
|
|
****************************************************************************}
|
|
|
|
constructor ttypesym.create(const n : string;const tt : ttype);
|
|
|
|
begin
|
|
inherited create(n);
|
|
typ:=typesym;
|
|
restype:=tt;
|
|
{$ifdef GDB}
|
|
isusedinstab := false;
|
|
{$endif GDB}
|
|
{ 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 loadsym(ppufile);
|
|
typ:=typesym;
|
|
{$ifdef GDB}
|
|
isusedinstab := false;
|
|
{$endif GDB}
|
|
ppufile.gettype(restype);
|
|
end;
|
|
|
|
|
|
function ttypesym.gettypedef:tdef;
|
|
begin
|
|
gettypedef:=restype.def;
|
|
end;
|
|
|
|
|
|
procedure ttypesym.deref;
|
|
begin
|
|
restype.resolve;
|
|
end;
|
|
|
|
|
|
procedure ttypesym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited writesym(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;
|
|
begin
|
|
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
|
|
ppufile.putderef(self);
|
|
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;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function ttypesym.stabstring : pchar;
|
|
var
|
|
stabchar : string[2];
|
|
short : string;
|
|
begin
|
|
if restype.def.deftype in tagtypes then
|
|
stabchar := 'Tt'
|
|
else
|
|
stabchar := 't';
|
|
short := '"'+name+':'+stabchar+tstoreddef(restype.def).numberstring
|
|
+'",'+tostr(N_LSYM)+',0,'+tostr(fileinfo.line)+',0';
|
|
stabstring := strpnew(short);
|
|
end;
|
|
|
|
procedure ttypesym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
{not stabs for forward defs }
|
|
if assigned(restype.def) then
|
|
if (restype.def.typesym = self) then
|
|
tstoreddef(restype.def).concatstabto(asmlist)
|
|
else
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
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 loadsym(ppufile);
|
|
typ:=syssym;
|
|
number:=ppufile.getlongint;
|
|
end;
|
|
|
|
destructor tsyssym.destroy;
|
|
begin
|
|
inherited destroy;
|
|
end;
|
|
|
|
procedure tsyssym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited writesym(ppufile);
|
|
ppufile.putlongint(number);
|
|
ppufile.writeentry(ibsyssym);
|
|
end;
|
|
|
|
{$ifdef GDB}
|
|
procedure tsyssym.concatstabto(asmlist : taasmoutput);
|
|
begin
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
TRTTISYM
|
|
****************************************************************************}
|
|
|
|
constructor trttisym.create(const n:string;rt:trttitype);
|
|
const
|
|
prefix : array[trttitype] of string[5]=('$rtti','$init');
|
|
begin
|
|
inherited create(prefix[rt]+n);
|
|
typ:=rttisym;
|
|
lab:=nil;
|
|
rttityp:=rt;
|
|
end;
|
|
|
|
|
|
constructor trttisym.ppuload(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited loadsym(ppufile);
|
|
typ:=rttisym;
|
|
lab:=nil;
|
|
rttityp:=trttitype(ppufile.getbyte);
|
|
end;
|
|
|
|
|
|
procedure trttisym.ppuwrite(ppufile:tcompilerppufile);
|
|
begin
|
|
inherited writesym(ppufile);
|
|
ppufile.putbyte(byte(rttityp));
|
|
ppufile.writeentry(ibrttisym);
|
|
end;
|
|
|
|
|
|
function trttisym.mangledname : string;
|
|
const
|
|
prefix : array[trttitype] of string[5]=('RTTI_','INIT_');
|
|
var
|
|
s : string;
|
|
p : tsymtable;
|
|
begin
|
|
s:='';
|
|
p:=owner;
|
|
while assigned(p) and (p.symtabletype=localsymtable) do
|
|
begin
|
|
s:=s+'_'+p.defowner.name;
|
|
p:=p.defowner.owner;
|
|
end;
|
|
if not(p.symtabletype in [globalsymtable,staticsymtable]) then
|
|
internalerror(200108265);
|
|
mangledname:=prefix[rttityp]+p.name^+s+'$_'+Copy(name,5,255);
|
|
end;
|
|
|
|
|
|
function trttisym.get_label:tasmsymbol;
|
|
begin
|
|
{ the label is always a global label }
|
|
if not assigned(lab) then
|
|
lab:=objectlibrary.newasmsymboltype(mangledname,AB_GLOBAL,AT_DATA);
|
|
get_label:=lab;
|
|
end;
|
|
|
|
|
|
{ persistent rtti generation }
|
|
procedure generate_rtti(p:tsym);
|
|
var
|
|
rsym : trttisym;
|
|
def : tstoreddef;
|
|
begin
|
|
{ rtti can only be generated for classes that are always typesyms }
|
|
if not(p.typ=typesym) then
|
|
internalerror(200108261);
|
|
def:=tstoreddef(ttypesym(p).restype.def);
|
|
{ only create rtti once for each definition }
|
|
if not(df_has_rttitable in def.defoptions) then
|
|
begin
|
|
{ definition should be in the same symtable as the symbol }
|
|
if p.owner<>def.owner then
|
|
internalerror(200108262);
|
|
{ create rttisym }
|
|
rsym:=trttisym.create(p.name,fullrtti);
|
|
p.owner.insert(rsym);
|
|
{ register rttisym in definition }
|
|
include(def.defoptions,df_has_rttitable);
|
|
def.rttitablesym:=rsym;
|
|
{ write rtti data }
|
|
def.write_child_rtti_data(fullrtti);
|
|
if (cs_create_smart in aktmoduleswitches) then
|
|
rttiList.concat(Tai_cut.Create);
|
|
rttiList.concat(Tai_symbol.Create(rsym.get_label,0));
|
|
def.write_rtti_data(fullrtti);
|
|
rttiList.concat(Tai_symbol_end.Create(rsym.get_label));
|
|
end;
|
|
end;
|
|
|
|
|
|
{ persistent init table generation }
|
|
procedure generate_inittable(p:tsym);
|
|
var
|
|
rsym : trttisym;
|
|
def : tstoreddef;
|
|
begin
|
|
{ anonymous types are also allowed for records that can be varsym }
|
|
case p.typ of
|
|
typesym :
|
|
def:=tstoreddef(ttypesym(p).restype.def);
|
|
varsym :
|
|
def:=tstoreddef(tvarsym(p).vartype.def);
|
|
else
|
|
internalerror(200108263);
|
|
end;
|
|
{ only create inittable once for each definition }
|
|
if not(df_has_inittable in def.defoptions) then
|
|
begin
|
|
{ definition should be in the same symtable as the symbol }
|
|
if p.owner<>def.owner then
|
|
internalerror(200108264);
|
|
{ create rttisym }
|
|
rsym:=trttisym.create(p.name,initrtti);
|
|
p.owner.insert(rsym);
|
|
{ register rttisym in definition }
|
|
include(def.defoptions,df_has_inittable);
|
|
def.inittablesym:=rsym;
|
|
{ write inittable data }
|
|
def.write_child_rtti_data(initrtti);
|
|
if (cs_create_smart in aktmoduleswitches) then
|
|
rttiList.concat(Tai_cut.Create);
|
|
rttiList.concat(Tai_symbol.Create(rsym.get_label,0));
|
|
def.write_rtti_data(initrtti);
|
|
rttiList.concat(Tai_symbol_end.Create(rsym.get_label));
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
end.
|
|
{
|
|
$Log$
|
|
Revision 1.70 2002-10-13 21:33:37 peter
|
|
* give correct fileposition for undefined forward procs
|
|
|
|
Revision 1.69 2002/10/05 12:43:29 carl
|
|
* fixes for Delphi 6 compilation
|
|
(warning : Some features do not work under Delphi)
|
|
|
|
Revision 1.68 2002/10/05 00:52:20 peter
|
|
* split boolean check in two lines for easier debugging
|
|
|
|
Revision 1.67 2002/09/26 12:04:53 florian
|
|
+ constsym with type=constguid can be written to ppu now,
|
|
fixes web bug 1820
|
|
|
|
Revision 1.66 2002/09/16 14:11:13 peter
|
|
* add argument to equal_paras() to support default values or not
|
|
|
|
Revision 1.65 2002/09/09 17:34:16 peter
|
|
* tdicationary.replace added to replace and item in a dictionary. This
|
|
is only allowed for the same name
|
|
* varsyms are inserted in symtable before the types are parsed. This
|
|
fixes the long standing "var longint : longint" bug
|
|
- consume_idlist and idstringlist removed. The loops are inserted
|
|
at the callers place and uses the symtable for duplicate id checking
|
|
|
|
Revision 1.64 2002/09/08 11:10:17 carl
|
|
* bugfix 2109 (bad imho, but only way)
|
|
|
|
Revision 1.63 2002/09/07 18:17:41 florian
|
|
+ tvarsym.paraitem added
|
|
|
|
Revision 1.62 2002/09/07 15:25:10 peter
|
|
* old logs removed and tabs fixed
|
|
|
|
Revision 1.61 2002/09/05 19:29:45 peter
|
|
* memdebug enhancements
|
|
|
|
Revision 1.60 2002/09/05 14:51:42 peter
|
|
* internalerror instead of crash in getprocdef
|
|
|
|
Revision 1.59 2002/09/03 16:26:27 daniel
|
|
* Make Tprocdef.defs protected
|
|
|
|
Revision 1.58 2002/09/01 08:01:16 daniel
|
|
* Removed sets from Tcallnode.det_resulttype
|
|
+ Added read/write notifications of variables. These will be usefull
|
|
for providing information for several optimizations. For example
|
|
the value of the loop variable of a for loop does matter is the
|
|
variable is read after the for loop, but if it's no longer used
|
|
or written, it doesn't matter and this can be used to optimize
|
|
the loop code generation.
|
|
|
|
Revision 1.57 2002/08/25 19:25:21 peter
|
|
* sym.insert_in_data removed
|
|
* symtable.insertvardata/insertconstdata added
|
|
* removed insert_in_data call from symtable.insert, it needs to be
|
|
called separatly. This allows to deref the address calculation
|
|
* procedures now calculate the parast addresses after the procedure
|
|
directives are parsed. This fixes the cdecl parast problem
|
|
* push_addr_param has an extra argument that specifies if cdecl is used
|
|
or not
|
|
|
|
Revision 1.56 2002/08/25 09:06:21 peter
|
|
* fixed loop in concat_procdefs
|
|
|
|
Revision 1.55 2002/08/20 16:54:40 peter
|
|
* write address of varsym always
|
|
|
|
Revision 1.54 2002/08/20 10:31:26 daniel
|
|
* Tcallnode.det_resulttype rewritten
|
|
|
|
Revision 1.53 2002/08/18 20:06:27 peter
|
|
* inlining is now also allowed in interface
|
|
* renamed write/load to ppuwrite/ppuload
|
|
* tnode storing in ppu
|
|
* nld,ncon,nbas are already updated for storing in ppu
|
|
|
|
Revision 1.52 2002/08/17 09:23:42 florian
|
|
* first part of procinfo rewrite
|
|
|
|
Revision 1.51 2002/08/16 14:24:59 carl
|
|
* issameref() to test if two references are the same (then emit no opcodes)
|
|
+ ret_in_reg to replace ret_in_acc
|
|
(fix some register allocation bugs at the same time)
|
|
+ save_std_register now has an extra parameter which is the
|
|
usedinproc registers
|
|
|
|
Revision 1.50 2002/08/13 21:40:57 florian
|
|
* more fixes for ppc calling conventions
|
|
|
|
Revision 1.49 2002/08/12 15:08:40 carl
|
|
+ stab register indexes for powerpc (moved from gdb to cpubase)
|
|
+ tprocessor enumeration moved to cpuinfo
|
|
+ linker in target_info is now a class
|
|
* many many updates for m68k (will soon start to compile)
|
|
- removed some ifdef or correct them for correct cpu
|
|
|
|
Revision 1.48 2002/08/11 14:32:28 peter
|
|
* renamed current_library to objectlibrary
|
|
|
|
Revision 1.47 2002/08/11 13:24:14 peter
|
|
* saving of asmsymbols in ppu supported
|
|
* asmsymbollist global is removed and moved into a new class
|
|
tasmlibrarydata that will hold the info of a .a file which
|
|
corresponds with a single module. Added librarydata to tmodule
|
|
to keep the library info stored for the module. In the future the
|
|
objectfiles will also be stored to the tasmlibrarydata class
|
|
* all getlabel/newasmsymbol and friends are moved to the new class
|
|
|
|
Revision 1.46 2002/07/23 10:13:23 daniel
|
|
* Added important comment
|
|
|
|
Revision 1.45 2002/07/23 09:51:26 daniel
|
|
* Tried to make Tprocsym.defs protected. I didn't succeed but the cleanups
|
|
are worth comitting.
|
|
|
|
Revision 1.44 2002/07/20 17:45:29 daniel
|
|
* Register variables are now possible for global variables too. This is
|
|
important for small programs without procedures.
|
|
|
|
Revision 1.43 2002/07/20 11:57:58 florian
|
|
* types.pas renamed to defbase.pas because D6 contains a types
|
|
unit so this would conflicts if D6 programms are compiled
|
|
+ Willamette/SSE2 instructions to assembler added
|
|
|
|
Revision 1.42 2002/07/11 14:41:31 florian
|
|
* start of the new generic parameter handling
|
|
|
|
}
|