fpc/compiler/new/symtable/symtablt.pas
1999-08-16 12:54:02 +00:00

387 lines
11 KiB
ObjectPascal

{
$Id$
This unit implements the different types of symbol tables
Copyright (C) 1999 by Daniel Mantione,
member of the Free Pascal development team
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.
****************************************************************************
}
{$ifdef TP}
{$N+,E+,F+}
{$endif}
unit symtablt;
interface
uses objects,cobjects,symtable,globtype;
type Pglobalsymtable=^Tglobalsymtable;
Pinterfacesymtable=^Tinterfacesymtable;
Pimplsymtable=^Tsymtable;
Pprocsymtable=^Tprocsymtable;
Punitsymtable=^Tunitsymtable;
Pobjectsymtable=^Tobjectsymtable;
Tglobalsymtable=object(Tcontainingsymtable)
constructor init;
{Checks if all used units are used.}
procedure check_units;
function tconstsymtodata(sym:Psym;len:longint):longint;virtual;
function varsymtodata(sym:Psym;len:longint):longint;virtual;
end;
Tinterfacesymtable=object(Tglobalsymtable)
unitid:word;
function varsymprefix:string;virtual;
end;
Timplsymtable=object(Tglobalsymtable)
unitid:word;
function varsymprefix:string;virtual;
end;
Tabstractrecordsymtable=object(Tcontainingsymtable)
procedure insert(sym:Psym);virtual;
function varsymtodata(sym:Psym;len:longint):longint;virtual;
end;
Precordsymtable=^Trecordsymtable;
Trecordsymtable=object(Tabstractsymtable)
end;
Tobjectsymtable=object(Tabstractrecordsymtable)
defowner:Pobjectsymtable;
function speedsearch(const s:stringid;
speedvalue:longint):Psym;virtual;
end;
Tprocsymtable=object(Tcontainingsymtable)
{Replaces the old local and paramsymtables.}
lexlevel:byte;
paramdatasize:longint;
{If this is a method, this points to the objectdef. It is
possible to make another Tmethodsymtable and move this field
to it, but I think the advantage is not worth it. (DM)}
method:Pdef;
procedure insert(sym:Psym);virtual;
function speedsearch(const s:stringid;
speedvalue:longint):Psym;virtual;
function varsymtodata(sym:Psym;len:longint):longint;virtual;
end;
Tunitsymtable=object(Tcontainingsymtable)
unittypecount:word;
unitsym:Psym;
constructor init(const n:string);
{Checks if all used units are used.}
procedure check_units;
function speedsearch(const s:stringid;
speedvalue:longint):Psym;virtual;
function tconstsymtodata(sym:Psym;len:longint):longint;virtual;
function varsymprefix:string;virtual;
destructor done;virtual;
end;
Twithsymtable=object(Tsymtable)
link:Pcontainingsymtable;
constructor init(Alink:Pcontainingsymtable);
function speedsearch(const s:stringid;
speedvalue:longint):Psym;virtual;
end;
implementation
uses symbols,files,globals,aasm,systems,defs,verbose;
function data_align(length:longint):longint;
begin
if length>2 then
data_align:=4
else if length>1 then
data_align:=2
else
data_align:=1;
end;
{****************************************************************************
Tglobalsymtable
****************************************************************************}
constructor Tglobalsymtable.init;
begin
inherited init;
index_growsize:=128;
end;
procedure Tglobalsymtable.check_units;
begin
end;
function Tglobalsymtable.tconstsymtodata(sym:Psym;len:longint):longint;
var ali:longint;
segment:Paasmoutput;
begin
if Ptypedconstsym(sym)^.is_really_const then
segment:=consts
else
segment:=datasegment;
if (cs_smartlink in aktmoduleswitches) then
segment^.concat(new(Pai_cut,init));
ali:=data_align(len);
align(datasize,ali);
{$ifdef GDB}
if cs_debuginfo in aktmoduleswitches then
concatstabto(segment);
{$endif GDB}
segment^.concat(new(Pai_symbol,initname_global(sym^.mangledname)));
end;
function Tglobalsymtable.varsymtodata(sym:Psym;len:longint):longint;
var ali:longint;
begin
if (cs_smartlink in aktmoduleswitches) then
bsssegment^.concat(new(Pai_cut,init));
ali:=data_align(len);
align(datasize,ali);
{$ifdef GDB}
if cs_debuginfo in aktmoduleswitches then
concatstabto(bsssegment);
{$endif GDB}
bsssegment^.concat(new(Pai_datablock,
init_global(sym^.mangledname,len)));
varsymtodata:=inherited varsymtodata(sym,len);
{This symbol can't be loaded to a register.}
exclude(Pvarsym(sym)^.properties,vo_regable);
end;
{****************************************************************************
Timplsymtable
****************************************************************************}
function Timplsymtable.varsymprefix:string;
begin
varsymprefix:='U_'+name^+'_';
end;
{****************************************************************************
Tinterfacesymtable
****************************************************************************}
function Tinterfacesymtable.varsymprefix:string;
begin
varsymprefix:='_'+name^+'$$$'+'_';
end;
{****************************************************************************
Tabstractrecordsymtable
****************************************************************************}
procedure Tabstractrecordsymtable.insert(sym:Psym);
begin
{ if typeof(sym)=typeof(Tenumsym) then
if owner<>nil then
owner^.insert(sym)
else
internalerror($990802)
else}
inherited insert(sym);
end;
function Tabstractrecordsymtable.varsymtodata(sym:Psym;
len:longint):longint;
begin
datasize:=(datasize+(aktpackrecords-1)) and (not aktpackrecords-1);
varsymtodata:=inherited varsymtodata(sym,len);
end;
{****************************************************************************
Trecordsymtable
****************************************************************************}
{****************************************************************************
Tobjectsymtable
****************************************************************************}
function Tobjectsymtable.speedsearch(const s:stringid;
speedvalue:longint):Psym;
var r:Psym;
begin
r:=inherited speedsearch(s,speedvalue);
if (r<>nil) and (sp_static in Pprocdef(r)^.objprop) and
allow_only_static then
begin
message(sym_e_only_static_in_static);
speedsearch:=nil;
end
else
speedsearch:=r;
end;
{****************************************************************************
Tprocsymsymtable
****************************************************************************}
procedure Tprocsymtable.insert(sym:Psym);
begin
{ if (method<>nil) and (method^.search(sym^.name)<>nil) then}
inherited insert(sym)
{ else
duplicatesym(sym)};
end;
function Tprocsymtable.speedsearch(const s:stringid;
speedvalue:longint):Psym;
begin
speedsearch:=inherited speedsearch(s,speedvalue);
end;
function Tprocsymtable.varsymtodata(sym:Psym;
len:longint):longint;
var modulo:longint;
begin
if typeof(sym^)=typeof(Tparamsym) then
begin
varsymtodata:=paramdatasize;
paramdatasize:=align(datasize+len,target_os.stackalignment);
end
else
begin
{Sym must be a varsym.}
{Align datastructures >=4 on a dword.}
if len>=4 then
align(len,4)
else
{$ifdef m68k}
{Align datastructures with size 1,2,3 on a word.}
align(len,2);
{$else}
{Align datastructures with size 2 or 3 on a word.}
if len>=2 then
align(len,2);
{$endif}
varsymtodata:=inherited varsymtodata(sym,len);
end;
end;
{****************************************************************************
Tunitsymtable
****************************************************************************}
constructor Tunitsymtable.init(const n:string);
begin
inherited init;
name:=stringdup(n);
index_growsize:=128;
end;
procedure Tunitsymtable.check_units;
begin
end;
function Tunitsymtable.speedsearch(const s:stringid;
speedvalue:longint):Psym;
var r:Psym;
begin
r:=inherited speedsearch(s,speedvalue);
{ if unitsym<>nil then
Punitsym(unitsym)^.refs;}
{ if (r^.typ=unitsym) and assigned(current_module) and
(current_module^.interfacesymtable<>@self) then
r:=nil;}
speedsearch:=r;
end;
function Tunitsymtable.tconstsymtodata(sym:Psym;len:longint):longint;
var ali:longint;
segment:Paasmoutput;
begin
if Ptypedconstsym(sym)^.is_really_const then
segment:=consts
else
segment:=datasegment;
if (cs_smartlink in aktmoduleswitches) then
segment^.concat(new(Pai_cut,init));
ali:=data_align(len);
align(datasize,ali);
{$ifdef GDB}
if cs_debuginfo in aktmoduleswitches then
concatstabto(segment);
{$endif GDB}
if (cs_smartlink in aktmoduleswitches) then
segment^.concat(new(Pai_symbol,initname_global(sym^.mangledname)))
else
segment^.concat(new(Pai_symbol,initname(sym^.mangledname)));
end;
function Tunitsymtable.varsymprefix:string;
begin
varsymprefix:='U_'+name^+'_';
end;
destructor Tunitsymtable.done;
begin
stringdispose(name);
inherited done;
end;
{****************************************************************************
Twithsymtable
****************************************************************************}
constructor Twithsymtable.init(Alink:Pcontainingsymtable);
begin
inherited init;
link:=Alink;
end;
function Twithsymtable.speedsearch(const s:stringid;speedvalue:longint):Psym;
begin
speedsearch:=link^.speedsearch(s,speedvalue);
end;
end.