fpc/compiler/symtype.pas
2002-09-05 19:29:42 +00:00

631 lines
16 KiB
ObjectPascal

{
$Id$
Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
This unit handles the symbol tables
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 symtype;
{$i fpcdefs.inc}
interface
uses
{ common }
cutils,
{$ifdef MEMDEBUG}
cclasses,
{$endif MEMDEBUG}
{ global }
globtype,globals,
{ symtable }
symconst,symbase,
{ aasm }
aasmbase
;
type
{************************************************
Required Forwards
************************************************}
tsym = class;
{************************************************
TRef
************************************************}
tref = class
nextref : tref;
posinfo : tfileposinfo;
moduleindex : longint;
is_written : boolean;
constructor create(ref:tref;pos:pfileposinfo);
procedure freechain;
destructor destroy;override;
end;
{************************************************
TDef
************************************************}
tgetsymtable = (gs_none,gs_record,gs_local,gs_para);
tdef = class(tdefentry)
typesym : tsym; { which type the definition was generated this def }
defoptions : tdefoptions;
constructor create;
procedure deref;virtual;abstract;
procedure derefimpl;virtual;abstract;
function typename:string;
function gettypename:string;virtual;
function mangledparaname:string;
function getmangledparaname:string;virtual;abstract;
function size:longint;virtual;abstract;
function alignment:longint;virtual;abstract;
function getsymtable(t:tgetsymtable):tsymtable;virtual;
function is_publishable:boolean;virtual;abstract;
function needs_inittable:boolean;virtual;abstract;
end;
{************************************************
TSym
************************************************}
{ this object is the base for all symbol objects }
tsym = class(tsymentry)
_realname : pstring;
fileinfo : tfileposinfo;
symoptions : tsymoptions;
constructor create(const n : string);
destructor destroy;override;
function realname:string;
procedure deref;virtual;abstract;
function gettypedef:tdef;virtual;
end;
{************************************************
TType
************************************************}
ttype = object
def : tdef;
sym : tsym;
procedure reset;
procedure setdef(p:tdef);
procedure setsym(p:tsym);
procedure resolve;
end;
{************************************************
TSymList
************************************************}
psymlistitem = ^tsymlistitem;
tsymlistitem = record
sltype : tsltype;
sym : tsym;
value : longint;
next : psymlistitem;
end;
tsymlist = class
def : tdef;
firstsym,
lastsym : psymlistitem;
constructor create;
destructor destroy;override;
function empty:boolean;
procedure setdef(p:tdef);
procedure addsym(slt:tsltype;p:tsym);
procedure addconst(slt:tsltype;v:longint);
procedure clear;
function getcopy:tsymlist;
procedure resolve;
end;
{ resolving }
procedure resolvesym(var sym:pointer);
procedure resolvedef(var def:pointer);
{$ifdef MEMDEBUG}
var
membrowser,
memrealnames,
memmanglednames,
memprocparast,
memproclocalst,
memprocnodetree : tmemdebug;
{$endif MEMDEBUG}
implementation
uses
verbose,
fmodule;
{****************************************************************************
Tdef
****************************************************************************}
constructor tdef.create;
begin
inherited create;
deftype:=abstractdef;
owner := nil;
typesym := nil;
defoptions:=[];
end;
function tdef.typename:string;
begin
if assigned(typesym) and
not(deftype=procvardef) and
assigned(typesym._realname) and
(typesym._realname^[1]<>'$') then
typename:=typesym._realname^
else
typename:=gettypename;
end;
function tdef.gettypename : string;
begin
gettypename:='<unknown type>'
end;
function tdef.mangledparaname:string;
begin
if assigned(typesym) then
mangledparaname:=typesym.name
else
mangledparaname:=getmangledparaname;
end;
function tdef.getsymtable(t:tgetsymtable):tsymtable;
begin
getsymtable:=nil;
end;
{****************************************************************************
TSYM (base for all symtypes)
****************************************************************************}
constructor tsym.create(const n : string);
begin
if n[1]='$' then
inherited createname(copy(n,2,255))
else
inherited createname(upper(n));
_realname:=stringdup(n);
typ:=abstractsym;
symoptions:=[];
end;
destructor tsym.destroy;
begin
{$ifdef MEMDEBUG}
memrealnames.start;
{$endif MEMDEBUG}
stringdispose(_realname);
{$ifdef MEMDEBUG}
memrealnames.stop;
{$endif MEMDEBUG}
inherited destroy;
end;
function tsym.realname : string;
begin
if assigned(_realname) then
realname:=_realname^
else
realname:=name;
end;
function tsym.gettypedef:tdef;
begin
gettypedef:=nil;
end;
{****************************************************************************
TRef
****************************************************************************}
constructor tref.create(ref :tref;pos : pfileposinfo);
begin
nextref:=nil;
if pos<>nil then
posinfo:=pos^;
if assigned(current_module) then
moduleindex:=current_module.unit_index;
if assigned(ref) then
ref.nextref:=self;
is_written:=false;
end;
procedure tref.freechain;
var
p,q : tref;
begin
p:=nextref;
nextref:=nil;
while assigned(p) do
begin
q:=p.nextref;
p.free;
p:=q;
end;
end;
destructor tref.destroy;
begin
nextref:=nil;
end;
{****************************************************************************
TType
****************************************************************************}
procedure ttype.reset;
begin
def:=nil;
sym:=nil;
end;
procedure ttype.setdef(p:tdef);
begin
def:=p;
sym:=nil;
end;
procedure ttype.setsym(p:tsym);
begin
sym:=p;
def:=p.gettypedef;
if not assigned(def) then
internalerror(1234005);
end;
procedure ttype.resolve;
begin
if assigned(sym) then
begin
resolvesym(pointer(sym));
setsym(sym);
end
else
resolvedef(pointer(def));
end;
{****************************************************************************
TSymList
****************************************************************************}
constructor tsymlist.create;
begin
def:=nil; { needed for procedures }
firstsym:=nil;
lastsym:=nil;
end;
destructor tsymlist.destroy;
begin
clear;
end;
function tsymlist.empty:boolean;
begin
empty:=(firstsym=nil);
end;
procedure tsymlist.clear;
var
hp : psymlistitem;
begin
while assigned(firstsym) do
begin
hp:=firstsym;
firstsym:=firstsym^.next;
dispose(hp);
end;
firstsym:=nil;
lastsym:=nil;
def:=nil;
end;
procedure tsymlist.setdef(p:tdef);
begin
def:=p;
end;
procedure tsymlist.addsym(slt:tsltype;p:tsym);
var
hp : psymlistitem;
begin
if not assigned(p) then
internalerror(200110203);
new(hp);
hp^.sltype:=slt;
hp^.sym:=p;
hp^.value:=0;
hp^.next:=nil;
if assigned(lastsym) then
lastsym^.next:=hp
else
firstsym:=hp;
lastsym:=hp;
end;
procedure tsymlist.addconst(slt:tsltype;v:longint);
var
hp : psymlistitem;
begin
new(hp);
hp^.sltype:=slt;
hp^.sym:=nil;
hp^.value:=v;
hp^.next:=nil;
if assigned(lastsym) then
lastsym^.next:=hp
else
firstsym:=hp;
lastsym:=hp;
end;
function tsymlist.getcopy:tsymlist;
var
hp : tsymlist;
hp2 : psymlistitem;
hpn : psymlistitem;
begin
hp:=tsymlist.create;
hp.def:=def;
hp2:=firstsym;
while assigned(hp2) do
begin
new(hpn);
hpn^:=hp2^;
hpn^.next:=nil;
if assigned(hp.lastsym) then
hp.lastsym^.next:=hpn
else
hp.firstsym:=hpn;
hp.lastsym:=hpn;
hp2:=hp2^.next;
end;
getcopy:=hp;
end;
procedure tsymlist.resolve;
var
hp : psymlistitem;
begin
resolvedef(pointer(def));
hp:=firstsym;
while assigned(hp) do
begin
if assigned(hp^.sym) then
resolvesym(pointer(hp^.sym));
hp:=hp^.next;
end;
end;
{*****************************************************************************
Symbol / Definition Resolving
*****************************************************************************}
procedure resolvederef(var p:tderef;var st:tsymtable;var idx:word);
var
hp : tderef;
pd : tdef;
begin
st:=nil;
idx:=0;
while assigned(p) do
begin
case p.dereftype of
derefaktrecordindex :
begin
st:=aktrecordsymtable;
idx:=p.index;
end;
derefaktstaticindex :
begin
st:=aktstaticsymtable;
idx:=p.index;
end;
derefaktlocal :
begin
st:=aktlocalsymtable;
idx:=p.index;
end;
derefunit :
begin
{$ifdef NEWMAP}
st:=tsymtable(current_module.map^[p.index]^.globalsymtable);
{$else NEWMAP}
st:=tsymtable(current_module.map^[p.index]);
{$endif NEWMAP}
end;
derefrecord :
begin
pd:=tdef(st.getdefnr(p.index));
st:=pd.getsymtable(gs_record);
if not assigned(st) then
internalerror(556658);
end;
dereflocal :
begin
pd:=tdef(st.getdefnr(p.index));
st:=pd.getsymtable(gs_local);
if not assigned(st) then
internalerror(556658);
end;
derefpara :
begin
pd:=tdef(st.getdefnr(p.index));
st:=pd.getsymtable(gs_para);
if not assigned(st) then
internalerror(556658);
end;
derefindex :
begin
idx:=p.index;
end;
else
internalerror(556658);
end;
hp:=p;
p:=p.next;
hp.free;
end;
end;
procedure resolvedef(var def:pointer);
var
st : tsymtable;
idx : word;
begin
resolvederef(tderef(pointer(def)),st,idx);
if assigned(st) then
def:=tdef(st.getdefnr(idx))
else
def:=nil;
end;
procedure resolvesym(var sym:pointer);
var
st : tsymtable;
idx : word;
begin
resolvederef(tderef(pointer(sym)),st,idx);
if assigned(st) then
sym:=tsym(st.getsymnr(idx))
else
sym:=nil;
end;
{$ifdef MEMDEBUG}
initialization
membrowser:=TMemDebug.create('BrowserRefs');
membrowser.stop;
memrealnames:=TMemDebug.create('Realnames');
memrealnames.stop;
memmanglednames:=TMemDebug.create('Manglednames');
memmanglednames.stop;
memprocparast:=TMemDebug.create('ProcParaSt');
memprocparast.stop;
memproclocalst:=TMemDebug.create('ProcLocalSt');
memproclocalst.stop;
memprocnodetree:=TMemDebug.create('ProcNodeTree');
memprocnodetree.stop;
finalization
membrowser.free;
memrealnames.free;
memmanglednames.free;
memprocparast.free;
memproclocalst.free;
memprocnodetree.free;
{$endif MEMDEBUG}
end.
{
$Log$
Revision 1.22 2002-09-05 19:29:46 peter
* memdebug enhancements
Revision 1.21 2002/08/18 20:06:28 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.20 2002/08/11 13:24:16 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.19 2002/07/01 18:46:29 peter
* internal linker
* reorganized aasm layer
Revision 1.18 2002/05/18 13:34:21 peter
* readded missing revisions
Revision 1.17 2002/05/16 19:46:45 carl
+ defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
+ try to fix temp allocation (still in ifdef)
+ generic constructor calls
+ start of tassembler / tmodulebase class cleanup
Revision 1.15 2002/05/12 16:53:15 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function
* -CR checks also class typecasts at runtime by changing them
into as
* fixed compiler to cycle with the -CR option
* fixed stabs with elf writer, finally the global variables can
be watched
* removed a lot of routines from cga unit and replaced them by
calls to cgobj
* u32bit-s32bit updates for and,or,xor nodes. When one element is
u32bit then the other is typecasted also to u32bit without giving
a rangecheck warning/error.
* fixed pascal calling method with reversing also the high tree in
the parast, detected by tcalcst3 test
Revision 1.14 2002/04/19 15:46:04 peter
* mangledname rewrite, tprocdef.mangledname is now created dynamicly
in most cases and not written to the ppu
* add mangeledname_prefix() routine to generate the prefix of
manglednames depending on the current procedure, object and module
* removed static procprefix since the mangledname is now build only
on demand from tprocdef.mangledname
}