fpc/compiler/new/symtable/defs.pas
daniel a511be87c4 * Changed names of procedures flags
*  Changed VMT generation
2000-03-16 12:52:47 +00:00

3149 lines
88 KiB
ObjectPascal

{
$Id$
Copyright (C) 1998-2000 by Daniel Mantione
and other members of the Free Pascal development team
This unit handles definitions
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 defs;
interface
uses symtable,objects,{$IFDEF TP}xobjects,{$ENDIF}
cobjects,symtablt,globtype
{$ifdef i386}
,cpubase
{$endif}
{$ifdef m68k}
,m68k
{$endif}
{$ifdef alpha}
,alpha
{$endif};
type Targconvtyp=(act_convertable,act_equal,act_exact);
Tvarspez=(vs_value,vs_const,vs_var);
Tobjoption=(oo_has_abstract, {The object/class has
an abstract method => no
instances can be created.}
oo_is_class, {The object is a class.}
oo_has_virtual, {The object/class has
virtual methods.}
oo_isforward, {The class is only a forward
declared yet.}
oo_can_have_published, {True, if the class has rtti, i.e.
you can publish properties.}
oo_has_constructor, {The object/class has a
constructor.}
oo_has_destructor, {The object/class has a
destructor.}
{When has_virtual is set, has_vmt is also set....
oo_has_vmt, The object/class has a vmt.}
oo_has_msgstr,
oo_has_msgint,
oo_cppvmt); {The object/class uses an C++
compatible vmt, all members of
the same class tree, must use
then a C++ compatible vmt.}
Tobjoptionset=set of Tobjoption;
{Calling convention for tprocdef and Tprocvardef.}
Tproccalloption=(po_call_none,
po_call_clearstack, {Use IBM flat calling
convention. (Used by GCC.)}
po_call_leftright, {Push parameters from left to
right.}
po_call_cdecl, {Procedure uses C styled
calling.}
po_call_register, {Procedure uses register
(fastcall) calling.}
po_call_stdcall, {Procedure uses stdcall
call.}
po_call_safecall, {Safe call calling
conventions.}
po_call_palmossyscall, {Procedure is a PalmOS
system call.}
po_call_system,
po_call_inline, {Procedure is an assembler
macro.}
po_call_internproc, {Procedure has compiler
magic.}
po_call_internconst); {Procedure has constant
evaluator intern.}
Tproccalloptionset=set of Tproccalloption;
{Basic type for tprocdef and tprocvardef }
Tproctypeoption=(po_type_none,
po_type_proginit, {Program initialization.}
po_type_unitinit, {Unit initialization.}
po_type_unitfinalize, {Unit finalization.}
po_type_constructor, {Procedure is a constructor.}
po_type_destructor, {Procedure is a destructor.}
po_type_operator); {Procedure defines an
operator.}
{Other options for Tprocdef and Tprocvardef.}
Tprocoption=(po_none,
po_classmethod, {Class method.}
po_virtualmethod, {Procedure is a virtual method.}
po_abstractmethod, {Procedure is an abstract method.}
po_staticmethod, {Static method.}
po_overridingmethod, {Method with override directive.}
po_methodpointer, {Method pointer, only in procvardef, also
used for 'with object do'.}
po_containsself, {Self is passed explicit to the
compiler.}
po_interrupt, {Procedure is an interrupt handler.}
po_iocheck, {IO checking should be done after a call
to the procedure.}
po_assembler, {Procedure is written in assembler.}
po_msgstr, {Method for string message handling.}
po_msgint, {Method for int message handling.}
po_exports, {Procedure has export directive (needed
for OS/2).}
po_external, {Procedure is external (in other object
or lib).}
po_savestdregs, {Save std regs cdecl and stdcall need
that!}
po_saveregisters); {Save all registers }
Tprocoptionset=set of Tprocoption;
Tarrayoption=(ap_variant,ap_constructor,ap_arrayofconst);
Tarrayoptionset=set of Tarrayoption;
Pparameter=^Tparameter;
Tparameter=object(Tobject)
data:Psym;
paratyp:Tvarspez;
argconvtyp:Targconvtyp;
convertlevel:byte;
register:Tregister;
end;
Tfiletype=(ft_text,ft_typed,ft_untyped);
Pfiledef=^Tfiledef;
Tfiledef=object(Tdef)
filetype:Tfiletype;
definition:Pdef;
constructor init(Aowner:Pcontainingsymtable;
ft:Tfiletype;tas:Pdef);
constructor load(var s:Tstream);
procedure deref;virtual;
function gettypename:string;virtual;
procedure setsize;
{$ifdef GDB}
function stabstring:Pchar;virtual;
procedure concatstabto(asmlist:Paasmoutput);virtual;
{$endif GDB}
procedure store(var s:Tstream);virtual;
end;
Pformaldef=^Tformaldef;
Tformaldef=object(Tdef)
constructor init(Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
procedure store(var s:Tstream);virtual;
{$ifdef GDB}
function stabstring:Pchar;virtual;
procedure concatstabto(asmlist:Paasmoutput);virtual;
{$endif GDB}
function gettypename:string;virtual;
end;
Perrordef=^Terrordef;
Terrordef=object(Tdef)
{$IFDEF TP}
constructor init(Aowner:Pcontainingsymtable);
{$ENDIF}
{$ifdef GDB}
function stabstring:Pchar;virtual;
{$endif GDB}
function gettypename:string;virtual;
end;
Pabstractpointerdef=^Tabstractpointerdef;
Tabstractpointerdef=object(Tdef)
definition:Pdef;
defsym:Psym;
constructor init(Aowner:Pcontainingsymtable;def:Pdef);
constructor load(var s:Tstream);
procedure deref;virtual;
procedure store(var s:Tstream);virtual;
{$ifdef GDB}
function stabstring:Pchar;virtual;
procedure concatstabto(asmlist:Paasmoutput);virtual;
{$endif GDB}
end;
Ppointerdef=^Tpointerdef;
Tpointerdef=object(Tabstractpointerdef)
is_far:boolean;
constructor initfar(Aowner:Pcontainingsymtable;def:Pdef);
constructor load(var s:Tstream);
procedure store(var s:Tstream);virtual;
function gettypename:string;virtual;
end;
Pclassrefdef=^Tclassrefdef;
Tclassrefdef=object(Tpointerdef)
{$IFDEF TP}
constructor init(Aowner:Pcontainingsymtable;def:Pdef);
{$ENDIF TP}
{$ifdef GDB}
function stabstring : pchar;virtual;
procedure concatstabto(asmlist : paasmoutput);virtual;
{$endif GDB}
function gettypename:string;virtual;
end;
Pvmtentry=^Tvmtentry;
Pglobalvmtentry=^Tglobalvmtentry;
Plocalvmtentry=^Tlocalvmtentry;
Pobjectdef=^Tobjectdef;
Pabstractprocdef=^Pabstractprocdef;
Pprocvardef=^Tprocvardef;
Pprocdef = ^Tprocdef;
Tvmtentry=object(Tobject)
owner:Pobjectdef;
constructor init(Aowner:Pobjectdef);
function mangledname:string;virtual;
end;
Tglobalvmtentry=object(Tvmtentry)
constructor init(Aowner:Pobjectdef;proc:Pprocdef);
function mangledname:string;virtual;
private
def:Pprocdef;
end;
Tlocalvmtentry=object(Tvmtentry)
constructor init(Aowner:Pobjectdef;proc:Pprocdef);
function mangledname:string;virtual;
private
name:Pstring;
end;
Tobjectdef=object(Tdef)
childof:Pobjectdef;
objname:Pstring;
privatesyms,
protectedsyms,
publicsyms:Pobjectsymtable;
options:Tobjoptionset;
{To be able to have a variable vmt position
and no vmt field for objects without virtuals.}
vmt_offset:longint;
{Contains Tvmtentry objects to describe the layout of the vmt.}
vmt_layout:Pcollection;
constructor init(const n:string;Aowner:Pcontainingsymtable;
parent:Pobjectdef;isclass:boolean);
constructor load(var s:Tstream);
procedure check_forwards;
function insert(Asym:Psym):boolean;
procedure insertvmt;
function is_related(d:Pobjectdef):boolean;
function search(const s:string;search_protected:boolean):Psym;
function speedsearch(const s:string;speedvalue:longint;
search_protected:boolean):Psym;virtual;
function size:longint;virtual;
procedure store(var s:Tstream);virtual;
function vmt_mangledname : string;
function rtti_name : string;
procedure set_parent(parent:Pobjectdef);
{$ifdef GDB}
function stabstring : pchar;virtual;
{$endif GDB}
procedure deref;virtual;
function needs_inittable:boolean;virtual;
procedure write_init_data;virtual;
procedure write_child_init_data;virtual;
{Rtti }
function get_rtti_label:string;virtual;
procedure generate_rtti;virtual;
procedure write_rtti_data;virtual;
procedure write_child_rtti_data;virtual;
function next_free_name_index:longint;
function is_publishable:boolean;virtual;
destructor done;virtual;
end;
Parraydef=^Tarraydef;
Tarraydef=object(Tdef)
lowrange,
highrange:Tconstant;
definition:Pdef;
rangedef:Pdef;
options:Tarrayoptionset;
constructor init(const l,h:Tconstant;rd:Pdef;
Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
function elesize:longint;
function gettypename:string;virtual;
procedure store(var s:Tstream);virtual;
{$ifdef GDB}
function stabstring : pchar;virtual;
procedure concatstabto(asmlist : paasmoutput);virtual;
{$endif GDB}
procedure deref;virtual;
function size : longint;virtual;
{ generates the ranges needed by the asm instruction BOUND (i386)
or CMP2 (Motorola) }
procedure genrangecheck;
{ returns the label of the range check string }
function getrangecheckstring : string;
function needs_inittable : boolean;virtual;
procedure write_rtti_data;virtual;
procedure write_child_rtti_data;virtual;
private
rangenr:longint;
end;
Penumdef=^Tenumdef;
Tenumdef=object(Tdef)
rangenr,
minval,
maxval:longint;
has_jumps:boolean;
symbols:Pcollection;
basedef:Penumdef;
constructor init(Aowner:Pcontainingsymtable);
constructor init_subrange(Abasedef:Penumdef;Amin,Amax:longint;
Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
procedure deref;virtual;
procedure calcsavesize;
function getrangecheckstring:string;
procedure genrangecheck;
procedure setmax(Amax:longint);
procedure setmin(Amin:longint);
procedure store(var s:Tstream);virtual;
{$ifdef GDB}
function stabstring:Pchar;virtual;
{$endif GDB}
procedure write_child_rtti_data;virtual;
procedure write_rtti_data;virtual;
function is_publishable : boolean;virtual;
function gettypename:string;virtual;
end;
Tbasetype=(uauto,uvoid,uchar,
u8bit,u16bit,u32bit,
s8bit,s16bit,s32bit,
bool8bit,bool16bit,bool32bit,
s64bit,u64bit,s64bitint,uwidechar);
Porddef=^Torddef;
Torddef=object(Tdef)
low,high:Tconstant;
rangenr:longint;
typ:Tbasetype;
constructor init(t:tbasetype;l,h:Tconstant;
Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
procedure store(var s:Tstream);virtual;
procedure setsize;
{ generates the ranges needed by the asm instruction BOUND }
{ or CMP2 (Motorola) }
procedure genrangecheck;
{ returns the label of the range check string }
function getrangecheckstring : string;
procedure write_rtti_data;virtual;
function is_publishable:boolean;virtual;
function gettypename:string;virtual;
{$ifdef GDB}
function stabstring:Pchar;virtual;
{$endif GDB}
end;
{S80real is dependant on the cpu, s64comp is also
dependant on the size (tp = 80bit for both)
The EXTENDED format exists on the motorola FPU
but it uses 96 bits instead of 80, with some
unused bits within the number itself! Pretty
complicated to support, so no support for the
moment.
S64comp is considered as a real because all
calculations are done by the fpu.}
Tfloattype=(s32real,s64real,s80real,s64comp,f16bit,f32bit);
Pfloatdef=^Tfloatdef;
Tfloatdef=object(tdef)
typ:Tfloattype;
constructor init(t:Tfloattype;Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
function is_publishable : boolean;virtual;
procedure setsize;
{$ifdef GDB}
function stabstring:Pchar;virtual;
{$endif GDB}
procedure store(var s:Tstream);virtual;
procedure write_rtti_data;virtual;
function gettypename:string;virtual;
end;
Tsettype=(normset,smallset,varset);
Psetdef=^Tsetdef;
Tsetdef=object(Tdef)
definition:Pdef;
settype:Tsettype;
constructor init(s:Pdef;high:longint;Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
procedure store(var s:Tstream);virtual;
{$ifdef GDB}
function stabstring : pchar;virtual;
procedure concatstabto(asmlist : paasmoutput);virtual;
{$endif GDB}
procedure deref;virtual;
function is_publishable : boolean;virtual;
procedure write_rtti_data;virtual;
procedure write_child_rtti_data;virtual;
function gettypename:string;virtual;
end;
Precorddef=^Trecorddef;
Trecorddef=object(Tdef)
symtable:Precordsymtable;
constructor init(s:Precordsymtable;Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
procedure store(var s:Tstream);virtual;
{$ifdef GDB}
function stabstring : pchar;virtual;
procedure concatstabto(asmlist : paasmoutput);virtual;
{$endif GDB}
procedure deref;virtual;
function needs_inittable : boolean;virtual;
procedure write_rtti_data;virtual;
procedure write_init_data;virtual;
procedure write_child_rtti_data;virtual;
procedure write_child_init_data;virtual;
function gettypename:string;virtual;
destructor done;virtual;
end;
{String types}
Tstringtype=(st_default,st_shortstring,st_longstring,
st_ansistring,st_widestring);
{This object needs to be splitted into multiple objects,
one for each stringtype. This is because all code in this
object is different for all string types.}
Pstringdef=^Tstringdef;
Tstringdef=object(Tdef)
string_typ:Tstringtype;
len:longint;
constructor shortinit(l:byte;Aowner:Pcontainingsymtable);
constructor shortload(var s:Tstream);
constructor longinit(l:longint;Aowner:Pcontainingsymtable);
constructor longload(var s:Tstream);
constructor ansiinit(l:longint;Aowner:Pcontainingsymtable);
constructor ansiload(var s:Tstream);
constructor wideinit(l:longint;Aowner:Pcontainingsymtable);
constructor wideload(var s:Tstream);
function stringtypname:string;
function size:longint;virtual;
procedure store(var s:Tstream);virtual;
function gettypename:string;virtual;
function is_publishable : boolean;virtual;
{ debug }
{$ifdef GDB}
function stabstring:Pchar;virtual;
procedure concatstabto(asmlist : Paasmoutput);virtual;
{$endif GDB}
{ init/final }
function needs_inittable : boolean;virtual;
{ rtti }
procedure write_rtti_data;virtual;
end;
Tabstractprocdef=object(Tdef)
{Saves a definition to the return type }
retdef:Pdef;
fpu_used:byte; {How many stack fpu must be empty.}
proctype:Tproctypeoption;
options:Tprocoptionset; {Save the procedure options.}
calloptions:Tproccalloptionset;
parameters:Pcollection;
constructor init(Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
destructor done;virtual;
procedure deref;virtual;
function demangled_paras:string;
function para_size:longint;
procedure store(var s:Tstream);virtual;
procedure test_if_fpu_result;
{$ifdef GDB}
function stabstring : pchar;virtual;
procedure concatstabto(asmlist : paasmoutput);virtual;
{$endif GDB}
end;
Tprocvardef=object(Tabstractprocdef)
{$IFDEF TP}
constructor init(Aowner:Pcontainingsymtable);
{$ENDIF TP}
function size:longint;virtual;
{$ifdef GDB}
function stabstring:Pchar;virtual;
procedure concatstabto(asmlist:Paasmoutput); virtual;
{$endif GDB}
procedure write_child_rtti_data;virtual;
function is_publishable:boolean;virtual;
procedure write_rtti_data;virtual;
function gettypename:string;virtual;
end;
{This datastructure is used to store the message information
when a procedure is declared as:
;message 'str';
;message int;
;virtual int;
}
Tmessageinf=record
case integer of
0:(str:Pchar);
1:(i:longint);
end;
{This object can be splitted into a Tprocdef, for normal procedures,
a Tmethoddef for methods, and a Tinlinedprocdef and a
Tinlinedmethoddef for inlined procedures.}
Tprocdef = object(tabstractprocdef)
messageinf:Tmessageinf;
{ where is this function defined, needed here because there
is only one symbol for all overloaded functions }
fileinfo:Tfileposinfo;
{ pointer to the local symbol table }
localst:Pprocsymtable;
_mangledname:Pstring;
{ it's a tree, but this not easy to handle }
{ used for inlined procs }
code : pointer;
vmt_index:longint;
{ true, if the procedure is only declared }
{ (forward procedure) }
references:Pcollection;
forwarddef,
{ true if the procedure is declared in the interface }
interfacedef : boolean;
{ check the problems of manglednames }
count : boolean;
is_used : boolean;
{ set which contains the modified registers }
usedregisters:Tregisterset;
constructor init(Aowner:Pcontainingsymtable);
constructor load(var s:Tstream);
procedure store(var s:Tstream);virtual;
{$ifdef GDB}
function cplusplusmangledname : string;
function stabstring : pchar;virtual;
procedure concatstabto(asmlist : paasmoutput);virtual;
{$endif GDB}
procedure deref;virtual;
function mangledname:string;
procedure setmangledname(const s:string);
procedure load_references;
function write_references:boolean;
destructor done;virtual;
end;
Pforwarddef=^Tforwarddef;
Tforwarddef=object(Tdef)
tosymname:string;
forwardpos:Tfileposinfo;
constructor init(Aowner:Pcontainingsymtable;
const s:string;const pos:Tfileposinfo);
function gettypename:string;virtual;
end;
{Relevant options for assigning a proc or a procvar to a procvar.}
const po_compatibility_options=[
po_classmethod,
po_staticmethod,
po_methodpointer,
po_containsself,
po_interrupt,
po_iocheck,
po_exports
];
var cformaldef:Pformaldef; {Unique formal definition.}
voiddef:Porddef; {Pointer to void (procedure) type.}
cchardef:Porddef; {Pointer to char type.}
booldef:Porddef; {Pointer to boolean type.}
u8bitdef:Porddef; {Pointer to 8-bit unsigned type.}
u16bitdef:Porddef; {Pointer to 16-bit unsigned type.}
u32bitdef:Porddef; {Pointer to 32-bit unsigned type.}
s32bitdef:Porddef; {Pointer to 32-bit signed type.}
cu64bitdef:Porddef; {Pointer to 64 bit unsigned def.}
cs64bitdef:Porddef; {Pointer to 64 bit signed def.}
voidpointerdef, {Pointer for Void-Pointerdef.}
charpointerdef, {Pointer for Char-Pointerdef.}
voidfarpointerdef:ppointerdef;
s32floatdef : pfloatdef; {Pointer for realconstn.}
s64floatdef : pfloatdef; {Pointer for realconstn.}
s80floatdef : pfloatdef; {Pointer to type of temp. floats.}
s32fixeddef : pfloatdef; {Pointer to type of temp. fixed.}
cshortstringdef, {Pointer to type of short string const.}
openshortstringdef, {Pointer to type of an openshortstring,
needed for readln().}
clongstringdef, {Pointer to type of long string const.}
cansistringdef, {Pointer to type of ansi string const.}
cwidestringdef:Pstringdef; {Pointer to type of wide string const.}
openchararraydef:Parraydef; {Pointer to type of an open array of
char, needed for readln().}
cfiledef:Pfiledef; {Get the same definition for all files
used for stabs.}
implementation
uses systems,symbols,verbose,globals,aasm,files,strings;
const {If you change one of the following contants,
you have also to change the typinfo unit
and the rtl/i386,template/rttip.inc files.}
tkunknown = 0;
tkinteger = 1;
tkchar = 2;
tkenumeration = 3;
tkfloat = 4;
tkset = 5;
tkmethod = 6;
tksstring = 7;
tkstring = tksstring;
tklstring = 8;
tkastring = 9;
tkwstring = 10;
tkvariant = 11;
tkarray = 12;
tkrecord = 13;
tkinterface = 14;
tkclass = 15;
tkobject = 16;
tkwchar = 17;
tkbool = 18;
otsbyte = 0;
otubyte = 1;
otsword = 2;
otuword = 3;
otslong = 4;
otulong = 5;
ftsingle = 0;
ftdouble = 1;
ftextended = 2;
ftcomp = 3;
ftcurr = 4;
ftfixed16 = 5;
ftfixed32 = 6;
{****************************************************************************
Tfiledef
****************************************************************************}
constructor Tfiledef.init(Aowner:Pcontainingsymtable;ft:Tfiletype;tas:Pdef);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
filetype:=ft;
definition:=tas;
setsize;
end;
constructor Tfiledef.load(var s:Tstream);
begin
inherited load(s);
{ filetype:=tfiletype(readbyte);
if filetype=ft_typed then
typed_as:=readdefref
else
typed_as:=nil;}
setsize;
end;
procedure Tfiledef.deref;
begin
{ if filetype=ft_typed then
resolvedef(typed_as);}
end;
procedure Tfiledef.setsize;
begin
case filetype of
ft_text:
savesize:=572;
ft_typed,ft_untyped:
savesize:=316;
end;
end;
procedure Tfiledef.store(var s:Tstream);
begin
{ inherited store(s);
writebyte(byte(filetype));
if filetype=ft_typed then
writedefref(typed_as);
current_ppu^.writeentry(ibfiledef);}
end;
function Tfiledef.gettypename : string;
begin
case filetype of
ft_untyped:
gettypename:='File';
ft_typed:
gettypename:='File Of '+definition^.typename;
ft_text:
gettypename:='Text'
end;
end;
{****************************************************************************
Tformaldef
****************************************************************************}
{Tformaldef is used for var parameters without a type.}
constructor Tformaldef.init(Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
savesize:=target_os.size_of_pointer;
end;
constructor Tformaldef.load(var s:Tstream);
begin
inherited load(s);
savesize:=target_os.size_of_pointer;
end;
procedure Tformaldef.store(var s:Tstream);
begin
inherited store(s);
{ current_ppu^.writeentry(ibformaldef);}
end;
function Tformaldef.gettypename:string;
begin
gettypename:='Var';
end;
{****************************************************************************
Terrordef
****************************************************************************}
{$IFDEF TP}
constructor Terrordef.init(Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
setparent(typeof(Tdef));
end;
{$ENDIF TP}
function Terrordef.gettypename:string;
begin
gettypename:='<erroneous type>';
end;
{****************************************************************************
Tabstractpointerdef
****************************************************************************}
constructor Tabstractpointerdef.init(Aowner:Pcontainingsymtable;def:Pdef);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
include(properties,dp_ret_in_acc);
definition:=def;
savesize:=target_os.size_of_pointer;
end;
constructor Tabstractpointerdef.load(var s:Tstream);
begin
inherited load(s);
(* {The real address in memory is calculated later (deref).}
definition:=readdefref; *)
savesize:=target_os.size_of_pointer;
end;
procedure Tabstractpointerdef.deref;
begin
{ resolvedef(definition);}
end;
procedure Tabstractpointerdef.store(var s:Tstream);
begin
inherited store(s);
{ writedefref(definition);
current_ppu^.writeentry(ibpointerdef);}
end;
{****************************************************************************
Tpointerdef
****************************************************************************}
constructor Tpointerdef.initfar(Aowner:Pcontainingsymtable;def:Pdef);
begin
inherited init(Aowner,def);
{$IFDEF TP}setparent(typeof(Tabstractpointerdef));{$ENDIF}
is_far:=true;
end;
constructor Tpointerdef.load(var s:Tstream);
begin
inherited load(s);
{ is_far:=(readbyte<>0);}
end;
function Tpointerdef.gettypename : string;
begin
gettypename:='^'+definition^.typename;
end;
procedure Tpointerdef.store(var s:Tstream);
begin
inherited store(s);
{ writebyte(byte(is_far));}
end;
{****************************************************************************
Tclassrefdef
****************************************************************************}
{$IFDEF TP}
constructor Tclassrefdef.init(Aowner:Pcontainingsymtable;def:Pdef);
begin
inherited init(Aowner,def);
setparent(typeof(Tpointerdef));
end;
{$ENDIF TP}
function Tclassrefdef.gettypename:string;
begin
gettypename:='Class of '+definition^.typename;
end;
{***************************************************************************
TVMTENTRY
***************************************************************************}
constructor Tvmtentry.init(Aowner:Pobjectdef);
begin
inherited init;
{$IFDEF TP}setparent(typeof(Tobject));{$ENDIF}
owner:=Aowner;
end;
function Tvmtentry.mangledname:string;
begin
abstract;
end;
{***************************************************************************
TGLOBALVMTENTRY
***************************************************************************}
constructor Tglobalvmtentry.init(Aowner:Pobjectdef;proc:Pprocdef);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tvmtentry));{$ENDIF TP}
def:=proc;
end;
function Tglobalvmtentry.mangledname:string;
begin
mangledname:=def^.mangledname;
end;
{***************************************************************************
TLOCALVMTENTRY
***************************************************************************}
constructor Tlocalvmtentry.init(Aowner:Pobjectdef;proc:Pprocdef);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tvmtentry));{$ENDIF TP}
if po_abstractmethod in proc^.options then
name:=stringdup('FPC_ABSTRACTERROR')
else
name:=stringdup(proc^.mangledname);
end;
function Tlocalvmtentry.mangledname:string;
begin
mangledname:=name^;
end;
{***************************************************************************
TOBJECTDEF
***************************************************************************}
constructor Tobjectdef.init(const n:string;Aowner:Pcontainingsymtable;
parent:Pobjectdef;isclass:boolean);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
new(publicsyms,init);
publicsyms^.name:=stringdup(n);
publicsyms^.defowner:=@self;
set_parent(parent);
objname:=stringdup(n);
if isclass then
begin
include(properties,dp_ret_in_acc);
include(options,oo_is_class);
end;
end;
procedure tobjectdef.set_parent(parent:Pobjectdef);
const inherited_options=[oo_has_virtual,
oo_has_constructor,oo_has_destructor];
begin
{Nothing to do if the parent was not forward !}
if childof=nil then
begin
childof:=parent;
{Some options are inherited...}
if parent<>nil then
begin
options:=options+parent^.options*inherited_options;
{Add the data of the anchestor class.}
inc(publicsyms^.datasize,parent^.publicsyms^.datasize);
if parent^.privatesyms<>nil then
begin
if privatesyms=nil then
new(privatesyms,init);
inc(privatesyms^.datasize,
parent^.privatesyms^.datasize);
end;
if parent^.protectedsyms<>nil then
begin
if protectedsyms<>nil then
new(protectedsyms,init);
inc(protectedsyms^.datasize,
parent^.protectedsyms^.datasize);
end;
if oo_has_virtual in (options*parent^.options) then
publicsyms^.datasize:=publicsyms^.datasize-
target_os.size_of_pointer;
{If parent has a vmt field then
the offset is the same for the child PM }
if [oo_has_virtual,oo_is_class]*parent^.options<>[] then
begin
vmt_offset:=parent^.vmt_offset;
include(options,oo_has_virtual);
end;
end;
savesize:=publicsyms^.datasize;
end;
end;
constructor Tobjectdef.load(var s:Tstream);
var oldread_member:boolean;
begin
inherited load(s);
(* savesize:=readlong;
vmt_offset:=readlong;
objname:=stringdup(readstring);
childof:=pobjectdef(readdefref);
options:=readlong;
oldread_member:=read_member;
read_member:=true;
publicsyms:=new(psymtable,loadas(objectsymtable));
read_member:=oldread_member;
publicsyms^.defowner:=@self;
{ publicsyms^.datasize:=savesize; }
publicsyms^.name := stringdup(objname^);
{ handles the predefined class tobject }
{ the last TOBJECT which is loaded gets }
{ it ! }
if (objname^='TOBJECT') and
isclass and (childof=nil) then
class_tobject:=@self;
has_rtti:=true;*)
end;
procedure Tobjectdef.insertvmt;
var o:Pobjectdef;
c:Pcollection;
i:word;
begin
if vmt_layout<>nil then
internalerror($990803);
{Make room for a vmtlink in the object.
First round up to aktpakrecords.}
publicsyms^.datasize:=align(publicsyms^.datasize,
packrecordalignment[aktpackrecords]);
vmt_offset:=publicsyms^.datasize;
publicsyms^.datasize:=publicsyms^.datasize+
target_os.size_of_pointer;
{Set up the vmt layout collection.
First search for a vmt in a parent object.}
o:=childof;
c:=nil;
while o<>nil do
begin
if o^.vmt_layout<>nil then
begin
c:=vmt_layout;
break;
end;
o:=o^.childof;
end;
if c=nil then
new(vmt_layout,init(8,8))
else
begin
{We should copy the vmt layout of our parent object. Our vmt
layout will change as soon as methods are overridden or when
new virtual methods are added.}
new(vmt_layout,init(c^.limit,8));
for i:=0 to c^.count-1 do
vmt_layout^.insert(c^.at(i));
end;
end;
procedure Tobjectdef.check_forwards;
begin
publicsyms^.check_forwards;
if oo_isforward in options then
begin
{ ok, in future, the forward can be resolved }
message1(sym_e_class_forward_not_resolved,objname^);
exclude(options,oo_isforward);
end;
end;
{ true, if self inherits from d (or if they are equal) }
function Tobjectdef.is_related(d:Pobjectdef):boolean;
var hp:Pobjectdef;
begin
hp:=@self;
is_related:=false;
while assigned(hp) do
begin
if hp=d then
begin
is_related:=true;
break;
end;
hp:=hp^.childof;
end;
end;
function Tobjectdef.insert(Asym:Psym):boolean;
var speedvalue:longint;
s:Psym;
op:Tobjpropset;
begin
{First check if the symbol already exists.}
s:=privatesyms^.speedsearch(Asym^.name,Asym^.speedvalue);
if s=nil then
protectedsyms^.speedsearch(Asym^.name,Asym^.speedvalue);
if s=nil then
publicsyms^.speedsearch(Asym^.name,Asym^.speedvalue);
if s<>nil then
duplicatesym(sym)
else
begin
{Asym is a Tprocsym, Tvarsym or Tpropertysym.}
if Asym^.is_object(typeof(Tprocsym)) then
op:=Pprocsym(Asym)^.objprop
else if Asym^.is_object(typeof(Tvarsym)) then
op:=Pvarsym(Asym)^.objprop
else if Asym^.is_object(typeof(Tpropertysym)) then
op:=Ppropertysym(Asym)^.objprop;
if sp_private in op then
insert:=privatesyms^.insert(Asym)
else if sp_protected in op then
insert:=protectedsyms^.insert(Asym)
else if sp_public in op then
insert:=publicsyms^.insert(Asym);
end;
end;
function Tobjectdef.search(const s:string;search_protected:boolean):Psym;
begin
search:=speedsearch(s,getspeedvalue(s),search_protected);
end;
function Tobjectdef.speedsearch(const s:string;speedvalue:longint;
search_protected:boolean):Psym;
var r:Psym;
begin
r:=publicsyms^.speedsearch(s,speedvalue);
{Privatesyms should be set to nil after compilation of the unit.
This way, private syms are not found by objects in other units.}
if (r=nil) and (privatesyms<>nil) then
r:=privatesyms^.speedsearch(s,speedvalue);
if (r=nil) and search_protected and (protectedsyms<>nil) then
r:=protectedsyms^.speedsearch(s,speedvalue);
end;
function Tobjectdef.size:longint;
begin
if oo_is_class in options then
size:=target_os.size_of_pointer
else
size:=publicsyms^.datasize;
end;
procedure tobjectdef.deref;
var oldrecsyms:Psymtable;
begin
{ resolvedef(pdef(childof));
oldrecsyms:=aktrecordsymtable;
aktrecordsymtable:=publicsyms;
publicsyms^.deref;
aktrecordsymtable:=oldrecsyms;}
end;
function Tobjectdef.vmt_mangledname:string;
begin
if not(oo_has_virtual in options) then
message1(parser_object_has_no_vmt,objname^);
vmt_mangledname:='VMT_'+owner^.name^+'$_'+objname^;
end;
function Tobjectdef.rtti_name:string;
begin
rtti_name:='RTTI_'+owner^.name^+'$_'+objname^;
end;
procedure Tobjectdef.store(var s:Tstream);
var oldread_member:boolean;
begin
inherited store(s);
(* writelong(size);
writelong(vmt_offset);
writestring(objname^);
writedefref(childof);
writelong(options);
current_ppu^.writeentry(ibobjectdef);
oldread_member:=read_member;
read_member:=true;
publicsyms^.writeas;
read_member:=oldread_member;*)
end;
procedure tobjectdef.write_child_init_data;
begin
end;
procedure Tobjectdef.write_init_data;
var b:byte;
begin
if oo_is_class in options then
b:=tkclass
else
b:=tkobject;
rttilist^.concat(new(Pai_const,init_8bit(b)));
{ generate the name }
rttilist^.concat(new(Pai_const,init_8bit(length(objname^))));
rttilist^.concat(new(Pai_string,init(objname^)));
(* rttilist^.concat(new(Pai_const,init_32bit(size)));
publicsyms^.foreach({$ifndef TP}@{$endif}count_inittable_fields);
rttilist^.concat(new(Pai_const,init_32bit(count)));
publicsyms^.foreach({$ifndef TP}@{$endif}write_field_inittable);*)
end;
function Tobjectdef.needs_inittable:boolean;
var oldb:boolean;
begin
{ there are recursive calls to needs_inittable possible, }
{ so we have to change to old value how else should }
{ we do that ? check_rec_rtti can't be a nested }
{ procedure of needs_rtti ! }
(* oldb:=binittable;
binittable:=false;
publicsyms^.foreach({$ifndef TP}@{$endif}check_rec_inittable);
needs_inittable:=binittable;
binittable:=oldb;*)
end;
destructor Tobjectdef.done;
var i:longint;
ve:Pvmtentry;
begin
{We should be carefull when disposing the vmt_layout; there are
vmt entries in it which are from methods of our ancestor, we
should not dispose these. So first set them to nil.}
for i:=0 to vmt_layout^.count do
if Pvmtentry(vmt_layout^.at(i))^.owner<>@self then
vmt_layout^.atput(i,nil);
dispose(vmt_layout,done);
if publicsyms<>nil then
dispose(publicsyms,done);
if privatesyms<>nil then
dispose(privatesyms,done);
if protectedsyms<>nil then
dispose(protectedsyms,done);
if oo_isforward in options then
message1(sym_e_class_forward_not_resolved,objname^);
stringdispose(objname);
inherited done;
end;
var count:longint;
procedure count_published_properties(sym:Pnamedindexobject);
{$ifndef fpc}far;{$endif}
begin
if sym^.is_object(typeof(Tpropertysym)) and
(ppo_published in Ppropertysym(sym)^.properties) then
inc(count);
end;
procedure write_property_info(sym:Pnamedindexobject);{$ifndef fpc}far;{$endif}
var proctypesinfo:byte;
procedure writeproc(proc:Pcollection;shiftvalue:byte);
var typvalue:byte;
begin
if proc=nil then
begin
rttilist^.concat(new(pai_const,init_32bit(1)));
typvalue:=3;
end
else if Psym(proc^.at(0))^.is_object(typeof(Tvarsym)) then
begin
rttilist^.concat(new(pai_const,init_32bit(
Pvarsym(sym)^.address)));
typvalue:=0;
end
else
begin
(* if (pprocdef(def)^.options and povirtualmethod)=0 then
begin
rttilist^.concat(new(pai_const_symbol,initname(pprocdef(def)^.mangledname)));
typvalue:=1;
end
else
begin
{Virtual method, write vmt offset.}
rttilist^.concat(new(pai_const,
init_32bit(Pprocdef(def)^.extnumber*4+12)));
typvalue:=2;
end;*)
end;
proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
end;
begin
if (typeof(sym^)=typeof(Tpropertysym)) and
(ppo_indexed in Ppropertysym(sym)^.properties) then
proctypesinfo:=$40
else
proctypesinfo:=0;
if (typeof(sym^)=typeof(Tpropertysym)) and
(ppo_published in Ppropertysym(sym)^.properties) then
begin
rttilist^.concat(new(pai_const_symbol,initname(
Ppropertysym(sym)^.definition^.get_rtti_label)));
writeproc(Ppropertysym(sym)^.readaccess,0);
writeproc(Ppropertysym(sym)^.writeaccess,2);
{ isn't it stored ? }
if (ppo_stored in Ppropertysym(sym)^.properties) then
begin
rttilist^.concat(new(pai_const,init_32bit(1)));
proctypesinfo:=proctypesinfo or (3 shl 4);
end
else
writeproc(ppropertysym(sym)^.storedaccess,4);
rttilist^.concat(new(pai_const,
init_32bit(ppropertysym(sym)^.index)));
rttilist^.concat(new(pai_const,
init_32bit(ppropertysym(sym)^.default)));
rttilist^.concat(new(pai_const,
init_16bit(count)));
inc(count);
rttilist^.concat(new(pai_const,init_8bit(proctypesinfo)));
rttilist^.concat(new(pai_const,
init_8bit(length(ppropertysym(sym)^.name))));
rttilist^.concat(new(pai_string,init(ppropertysym(sym)^.name)));
end;
end;
procedure generate_published_child_rtti(sym:Pnamedindexobject);
{$ifndef fpc}far;{$endif}
begin
if (typeof(sym^)=typeof(Tpropertysym)) and
(ppo_published in Ppropertysym(sym)^.properties) then
Ppropertysym(sym)^.definition^.get_rtti_label;
end;
procedure tobjectdef.write_child_rtti_data;
begin
publicsyms^.foreach({$ifndef TP}@{$endif}generate_published_child_rtti);
end;
procedure Tobjectdef.generate_rtti;
begin
{ getdatalabel(rtti_label);
write_child_rtti_data;
rttilist^.concat(new(pai_symbol,initname_global(rtti_name)));
rttilist^.concat(new(pai_label,init(rtti_label)));
write_rtti_data;}
end;
function Tobjectdef.next_free_name_index : longint;
var i:longint;
begin
if (childof<>nil) and (oo_can_have_published in childof^.options) then
i:=childof^.next_free_name_index
else
i:=0;
count:=0;
publicsyms^.foreach({$ifndef TP}@{$endif}count_published_properties);
next_free_name_index:=i+count;
end;
procedure tobjectdef.write_rtti_data;
begin
if oo_is_class in options then
rttilist^.concat(new(pai_const,init_8bit(tkclass)))
else
rttilist^.concat(new(pai_const,init_8bit(tkobject)));
{Generate the name }
rttilist^.concat(new(pai_const,init_8bit(length(objname^))));
rttilist^.concat(new(pai_string,init(objname^)));
{Write class type }
rttilist^.concat(new(pai_const_symbol,initname(vmt_mangledname)));
{ write owner typeinfo }
if (childof<>nil) and (oo_can_have_published in childof^.options) then
rttilist^.concat(new(pai_const_symbol,
initname(childof^.get_rtti_label)))
else
rttilist^.concat(new(pai_const,init_32bit(0)));
{Count total number of properties }
if (childof<>nil) and (oo_can_have_published in childof^.options) then
count:=childof^.next_free_name_index
else
count:=0;
{Write it>}
publicsyms^.foreach({$ifndef TP}@{$endif}count_published_properties);
rttilist^.concat(new(Pai_const,init_16bit(count)));
{ write unit name }
if owner^.name<>nil then
begin
rttilist^.concat(new(Pai_const,init_8bit(length(owner^.name^))));
rttilist^.concat(new(Pai_string,init(owner^.name^)));
end
else
rttilist^.concat(new(Pai_const,init_8bit(0)));
{ write published properties count }
count:=0;
publicsyms^.foreach({$ifndef TP}@{$endif}count_published_properties);
rttilist^.concat(new(pai_const,init_16bit(count)));
{ count is used to write nameindex }
{ but we need an offset of the owner }
{ to give each property an own slot }
if (childof<>nil) and (oo_can_have_published in childof^.options) then
count:=childof^.next_free_name_index
else
count:=0;
publicsyms^.foreach({$ifndef TP}@{$endif}write_property_info);
end;
function Tobjectdef.is_publishable:boolean;
begin
is_publishable:=oo_is_class in options;
end;
function Tobjectdef.get_rtti_label:string;
begin
get_rtti_label:=rtti_name;
end;
{***************************************************************************
TARRAYDEF
***************************************************************************}
constructor Tarraydef.init(const l,h:Tconstant;rd:Pdef;
Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
lowrange:=l;
highrange:=h;
rangedef:=rd;
end;
constructor Tarraydef.load(var s:Tstream);
begin
inherited load(s);
(* deftype:=arraydef;
{ the addresses are calculated later }
definition:=readdefref;
rangedef:=readdefref;
lowrange:=readlong;
highrange:=readlong;
IsArrayOfConst:=boolean(readbyte);*)
end;
function Tarraydef.getrangecheckstring:string;
begin
if (cs_create_smart in aktmoduleswitches) then
getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
else
getrangecheckstring:='R_'+tostr(rangenr);
end;
procedure Tarraydef.genrangecheck;
begin
if rangenr=0 then
begin
{Generates the data for range checking }
getlabelnr(rangenr);
if (cs_create_smart in aktmoduleswitches) then
datasegment^.concat(new(pai_symbol,
initname_global(getrangecheckstring,10)))
else
datasegment^.concat(new(pai_symbol,
initname(getrangecheckstring,10)));
datasegment^.concat(new(Pai_const,
init_8bit(byte(lowrange.signed))));
datasegment^.concat(new(Pai_const,
init_32bit(lowrange.values)));
datasegment^.concat(new(Pai_const,
init_8bit(byte(highrange.signed))));
datasegment^.concat(new(Pai_const,
init_32bit(highrange.values)));
end;
end;
procedure Tarraydef.deref;
begin
{ resolvedef(definition);
resolvedef(rangedef);}
end;
procedure Tarraydef.store(var s:Tstream);
begin
inherited store(s);
(* writedefref(definition);
writedefref(rangedef);
writelong(lowrange);
writelong(highrange);
writebyte(byte(IsArrayOfConst));
current_ppu^.writeentry(ibarraydef);*)
end;
function Tarraydef.elesize:longint;
begin
elesize:=definition^.size;
end;
function Tarraydef.size:longint;
begin
if (lowrange.signed) and (lowrange.values=-1) then
internalerror($990804);
if highrange.signed then
begin
{Check for overflow.}
if (highrange.values-lowrange.values=$7fffffff) or
(($7fffffff div elesize+elesize-1)>
(highrange.values-lowrange.values)) then
begin
{ message(sym_segment_too_large);}
size:=1;
end
else
size:=(highrange.values-lowrange.values+1)*elesize;
end
else
begin
{Check for overflow.}
if (highrange.valueu-lowrange.valueu=$7fffffff) or
(($7fffffff div elesize+elesize-1)>
(highrange.valueu-lowrange.valueu)) then
begin
{ message(sym_segment_too_small);}
size:=1;
end
else
size:=(highrange.valueu-lowrange.valueu+1)*elesize;
end;
end;
function Tarraydef.needs_inittable:boolean;
begin
needs_inittable:=definition^.needs_inittable;
end;
procedure Tarraydef.write_child_rtti_data;
begin
definition^.get_rtti_label;
end;
procedure tarraydef.write_rtti_data;
begin
rttilist^.concat(new(Pai_const,init_8bit(13)));
write_rtti_name;
{ size of elements }
rttilist^.concat(new(Pai_const,init_32bit(definition^.size)));
{ count of elements }
rttilist^.concat(new(Pai_const,
init_32bit(highrange.values-lowrange.values+1)));
{ element type }
rttilist^.concat(new(Pai_const_symbol,
initname(definition^.get_rtti_label)));
end;
function Tarraydef.gettypename:string;
var r:string;
begin
if [ap_arrayofconst,ap_constructor]*options<>[] then
gettypename:='array of const'
else if (lowrange.signed) and (lowrange.values=-1) then
gettypename:='Array Of '+definition^.typename
else
begin
r:='array[$1..$2 Of $3]';
if typeof(rangedef^)=typeof(Tenumdef) then
with Penumdef(rangedef)^.symbols^ do
begin
replace(r,'$1',Penumsym(at(0))^.name);
replace(r,'$2',Penumsym(at(count-1))^.name);
end
else
begin
if lowrange.signed then
replace(r,'$1',tostr(lowrange.values))
else
replace(r,'$1',tostru(lowrange.valueu));
if highrange.signed then
replace(r,'$2',tostr(highrange.values))
else
replace(r,'$2',tostr(highrange.valueu));
replace(r,'$3',definition^.typename);
end;
gettypename:=r;
end;
end;
{****************************************************************************
Tenumdef
****************************************************************************}
constructor Tenumdef.init(Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
include(properties,dp_ret_in_acc);
new(symbols,init(8,8));
calcsavesize;
end;
constructor Tenumdef.init_subrange(Abasedef:Penumdef;Amin,Amax:longint;
Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
minval:=Amin;
maxval:=Amax;
basedef:=Abasedef;
symbols:=Abasedef^.symbols;
calcsavesize;
end;
constructor Tenumdef.load(var s:Tstream);
begin
inherited load(s);
(* basedef:=penumdef(readdefref);
minval:=readlong;
maxval:=readlong;
savesize:=readlong;*)
end;
procedure Tenumdef.calcsavesize;
begin
if (aktpackenum=4) or (minval<0) or (maxval>65535) then
savesize:=4
else if (aktpackenum=2) or (minval<0) or (maxval>255) then
savesize:=2
else
savesize:=1;
end;
procedure Tenumdef.setmax(Amax:longint);
begin
maxval:=Amax;
calcsavesize;
end;
procedure Tenumdef.setmin(Amin:longint);
begin
minval:=Amin;
calcsavesize;
end;
procedure tenumdef.deref;
begin
{ resolvedef(pdef(basedef));}
end;
procedure Tenumdef.store(var s:Tstream);
begin
inherited store(s);
(* writedefref(basedef);
writelong(min);
writelong(max);
writelong(savesize);
current_ppu^.writeentry(ibenumdef);*)
end;
function tenumdef.getrangecheckstring : string;
begin
if (cs_create_smart in aktmoduleswitches) then
getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
else
getrangecheckstring:='R_'+tostr(rangenr);
end;
procedure tenumdef.genrangecheck;
begin
if rangenr=0 then
begin
{ generate two constant for bounds }
getlabelnr(rangenr);
if (cs_create_smart in aktmoduleswitches) then
datasegment^.concat(new(Pai_symbol,
initname_global(getrangecheckstring,8)))
else
datasegment^.concat(new(Pai_symbol,
initname(getrangecheckstring,8)));
datasegment^.concat(new(pai_const,init_32bit(minval)));
datasegment^.concat(new(pai_const,init_32bit(maxval)));
end;
end;
procedure Tenumdef.write_child_rtti_data;
begin
if assigned(basedef) then
basedef^.get_rtti_label;
end;
procedure Tenumdef.write_rtti_data;
var i:word;
begin
rttilist^.concat(new(pai_const,init_8bit(tkEnumeration)));
write_rtti_name;
case savesize of
1:
rttilist^.concat(new(Pai_const,init_8bit(otUByte)));
2:
rttilist^.concat(new(Pai_const,init_8bit(otUWord)));
4:
rttilist^.concat(new(Pai_const,init_8bit(otULong)));
end;
rttilist^.concat(new(pai_const,init_32bit(minval)));
rttilist^.concat(new(pai_const,init_32bit(maxval)));
if assigned(basedef) then
rttilist^.concat(new(pai_const_symbol,initname(basedef^.get_rtti_label)))
else
rttilist^.concat(new(pai_const,init_32bit(0)));
for i:=0 to symbols^.count-1 do
begin
rttilist^.concat(new(Pai_const,
init_8bit(length(Penumsym(symbols^.at(i))^.name))));
rttilist^.concat(new(Pai_string,
init(globals.lower(Penumsym(symbols^.at(i))^.name))));
end;
rttilist^.concat(new(pai_const,init_8bit(0)));
end;
function Tenumdef.is_publishable:boolean;
begin
is_publishable:=true;
end;
function Tenumdef.gettypename:string;
var i:word;
v:longint;
r:string;
begin
r:='(';
for i:=0 to symbols^.count-1 do
begin
v:=Penumsym(symbols^.at(i))^.value;
if (v>=minval) and (v<=maxval) then
r:=r+Penumsym(symbols^.at(i))^.name+',';
end;
{Turn ',' into ')'.}
r[length(r)]:=')';
end;
{****************************************************************************
Torddef
****************************************************************************}
constructor Torddef.init(t:Tbasetype;l,h:Tconstant;
Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
include(properties,dp_ret_in_acc);
low:=l;
high:=h;
typ:=t;
setsize;
end;
constructor Torddef.load(var s:Tstream);
begin
inherited load(s);
(* typ:=tbasetype(readbyte);
low:=readlong;
high:=readlong;*)
setsize;
end;
procedure Torddef.setsize;
begin
if typ=uauto then
begin
{Generate a unsigned range if high<0 and low>=0 }
if (low.values>=0) and (high.values<=255) then
typ:=u8bit
else if (low.signed) and (low.values>=-128) and (high.values<=127) then
typ:=s8bit
else if (low.values>=0) and (high.values<=65536) then
typ:=u16bit
else if (low.signed) and (low.values>=-32768) and (high.values<=32767) then
typ:=s16bit
else if low.signed then
typ:=s32bit
else
typ:=u32bit
end;
case typ of
u8bit,s8bit,uchar,bool8bit:
savesize:=1;
u16bit,s16bit,bool16bit:
savesize:=2;
s32bit,u32bit,bool32bit:
savesize:=4;
u64bit,s64bitint:
savesize:=8;
else
savesize:=0;
end;
rangenr:=0;
end;
function Torddef.getrangecheckstring:string;
begin
if (cs_create_smart in aktmoduleswitches) then
getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
else
getrangecheckstring:='R_'+tostr(rangenr);
end;
procedure Torddef.genrangecheck;
begin
if rangenr=0 then
begin
{Generate two constant for bounds.}
getlabelnr(rangenr);
if (cs_create_smart in aktmoduleswitches) then
datasegment^.concat(new(Pai_symbol,
initname_global(getrangecheckstring,10)))
else
datasegment^.concat(new(Pai_symbol,
initname(getrangecheckstring,10)));
datasegment^.concat(new(Pai_const,init_8bit(byte(low.signed))));
datasegment^.concat(new(Pai_const,init_32bit(low.values)));
datasegment^.concat(new(Pai_const,init_8bit(byte(high.signed))));
datasegment^.concat(new(Pai_const,init_32bit(high.values)));
end;
end;
procedure Torddef.store(var s:Tstream);
begin
inherited store(s);
(* writebyte(byte(typ));
writelong(low);
writelong(high);
current_ppu^.writeentry(iborddef);*)
end;
procedure Torddef.write_rtti_data;
const trans:array[uchar..bool8bit] of byte=
(otubyte,otubyte,otuword,otulong,
otsbyte,otsword,otslong,otubyte);
begin
case typ of
bool8bit:
rttilist^.concat(new(Pai_const,init_8bit(tkbool)));
uchar:
rttilist^.concat(new(Pai_const,init_8bit(tkchar)));
else
rttilist^.concat(new(Pai_const,init_8bit(tkinteger)));
end;
write_rtti_name;
rttilist^.concat(new(Pai_const,init_8bit(byte(trans[typ]))));
rttilist^.concat(new(Pai_const,init_32bit(low.values)));
rttilist^.concat(new(Pai_const,init_32bit(high.values)));
end;
function Torddef.is_publishable:boolean;
begin
is_publishable:=typ in [uchar..bool8bit];
end;
function Torddef.gettypename:string;
const names:array[Tbasetype] of string[20]=('<unknown type>',
'untyped','char','byte','word','dword','shortInt',
'smallint','longInt','boolean','wordbool',
'longbool','qword','int64','card64','widechar');
begin
gettypename:=names[typ];
end;
{****************************************************************************
Tfloatdef
****************************************************************************}
constructor Tfloatdef.init(t:Tfloattype;Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
if t=f32bit then
include(properties,dp_ret_in_acc);
typ:=t;
setsize;
end;
constructor Tfloatdef.load(var s:Tstream);
begin
inherited load(s);
(* typ:=Tfloattype(readbyte);*)
setsize;
end;
procedure tfloatdef.setsize;
begin
case typ of
f16bit:
savesize:=2;
f32bit,
s32real:
savesize:=4;
s64real:
savesize:=8;
s80real:
savesize:=extended_size;
s64comp:
savesize:=8;
else
savesize:=0;
end;
end;
procedure Tfloatdef.store(var s:Tstream);
begin
inherited store(s);
(* writebyte(byte(typ));
current_ppu^.writeentry(ibfloatdef);*)
end;
procedure Tfloatdef.write_rtti_data;
const translate:array[Tfloattype] of byte=
(ftsingle,ftdouble,ftextended,ftcomp,ftfixed16,ftfixed32);
begin
rttilist^.concat(new(Pai_const,init_8bit(tkfloat)));
write_rtti_name;
rttilist^.concat(new(Pai_const,init_8bit(translate[typ])));
end;
function Tfloatdef.is_publishable:boolean;
begin
is_publishable:=true;
end;
function Tfloatdef.gettypename:string;
const names:array[Tfloattype] of string[20]=(
'single','double','extended','comp','fixed','shortfixed');
begin
gettypename:=names[typ];
end;
{***************************************************************************
Tsetdef
***************************************************************************}
{ For i386 smallsets work,
for m68k there are problems
can be test by compiling with -dusesmallset PM }
{$ifdef i386}
{$define usesmallset}
{$endif i386}
constructor Tsetdef.init(s:Pdef;high:longint;Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
definition:=s;
if high<32 then
begin
settype:=smallset;
savesize:=4;
include(properties,dp_ret_in_acc);
end
else if high<256 then
begin
settype:=normset;
savesize:=32;
end
{$ifdef testvarsets}
else if high<$10000 then
begin
settype:=varset;
savesize:=4*((high+31) div 32);
end
{$endif testvarsets}
else
message(sym_e_ill_type_decl_set);
end;
constructor Tsetdef.load(var s:Tstream);
begin
inherited load(s);
(* setof:=readdefref;
settype:=tsettype(readbyte);
case settype of
normset:
savesize:=32;
varset:
savesize:=readlong;
smallset:
savesize:=sizeof(longint);
end;*)
end;
procedure Tsetdef.store(var s:Tstream);
begin
inherited store(s);
(* writedefref(setof);
writebyte(byte(settype));
if settype=varset then
writelong(savesize);
current_ppu^.writeentry(ibsetdef);*)
end;
procedure Tsetdef.deref;
begin
{ resolvedef(setof);}
end;
procedure Tsetdef.write_rtti_data;
begin
rttilist^.concat(new(pai_const,init_8bit(tkset)));
write_rtti_name;
rttilist^.concat(new(pai_const,init_8bit(otuLong)));
rttilist^.concat(new(pai_const_symbol,initname(definition^.get_rtti_label)));
end;
procedure Tsetdef.write_child_rtti_data;
begin
definition^.get_rtti_label;
end;
function Tsetdef.is_publishable:boolean;
begin
is_publishable:=settype=smallset;
end;
function Tsetdef.gettypename:string;
begin
gettypename:='set of '+definition^.typename;
end;
{***************************************************************************
Trecorddef
***************************************************************************}
constructor Trecorddef.init(s:Precordsymtable;Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
symtable:=s;
savesize:=symtable^.datasize;
end;
constructor Trecorddef.load(var s:Tstream);
var oldread_member:boolean;
begin
(* inherited load(s);
savesize:=readlong;
oldread_member:=read_member;
read_member:=true;
symtable:=new(psymtable,loadas(recordsymtable));
read_member:=oldread_member;
symtable^.defowner := @self;*)
end;
destructor Trecorddef.done;
begin
if symtable<>nil then
dispose(symtable,done);
inherited done;
end;
var
binittable : boolean;
procedure check_rec_inittable(s:Pnamedindexobject);
begin
if (typeof(s^)=typeof(Tvarsym)) and
((typeof((Pvarsym(s)^.definition^))<>typeof(Tobjectdef)) or
not (oo_is_class in Pobjectdef(Pvarsym(s)^.definition)^.options)) then
binittable:=pvarsym(s)^.definition^.needs_inittable;
end;
function Trecorddef.needs_inittable:boolean;
var oldb:boolean;
begin
{ there are recursive calls to needs_rtti possible, }
{ so we have to change to old value how else should }
{ we do that ? check_rec_rtti can't be a nested }
{ procedure of needs_rtti ! }
oldb:=binittable;
binittable:=false;
symtable^.foreach({$ifndef TP}@{$endif}check_rec_inittable);
needs_inittable:=binittable;
binittable:=oldb;
end;
procedure Trecorddef.deref;
var oldrecsyms:Psymtable;
begin
(* oldrecsyms:=aktrecordsymtable;
aktrecordsymtable:=symtable;
{ now dereference the definitions }
symtable^.deref;
aktrecordsymtable:=oldrecsyms;*)
end;
procedure Trecorddef.store(var s:Tstream);
var oldread_member:boolean;
begin
(* oldread_member:=read_member;
read_member:=true;
inherited store(s);
writelong(savesize);
current_ppu^.writeentry(ibrecorddef);
self.symtable^.writeas;
read_member:=oldread_member;*)
end;
procedure count_inittable_fields(sym:Pnamedindexobject);
{$ifndef fpc}far;{$endif}
begin
if (typeof(sym^)=typeof(Tvarsym)) and
(Pvarsym(sym)^.definition^.needs_inittable) then
inc(count);
end;
procedure count_fields(sym:Pnamedindexobject);{$ifndef fpc}far;{$endif}
begin
inc(count);
end;
procedure write_field_inittable(sym:Pnamedindexobject);
{$ifndef fpc}far;{$endif}
begin
if (typeof(sym^)=typeof(Tvarsym)) and
Pvarsym(sym)^.definition^.needs_inittable then
begin
rttilist^.concat(new(Pai_const_symbol,
init(pvarsym(sym)^.definition^.get_inittable_label)));
rttilist^.concat(new(Pai_const,
init_32bit(pvarsym(sym)^.address)));
end;
end;
procedure write_field_rtti(sym:Pnamedindexobject);{$ifndef fpc}far;{$endif}
begin
rttilist^.concat(new(Pai_const_symbol,
initname(Pvarsym(sym)^.definition^.get_rtti_label)));
rttilist^.concat(new(Pai_const,
init_32bit(Pvarsym(sym)^.address)));
end;
procedure generate_child_inittable(sym:Pnamedindexobject);
{$ifndef fpc}far;{$endif}
begin
if (typeof(sym^)=typeof(Tvarsym)) and
Pvarsym(sym)^.definition^.needs_inittable then
{Force inittable generation }
Pvarsym(sym)^.definition^.get_inittable_label;
end;
procedure generate_child_rtti(sym:Pnamedindexobject);
{$ifndef fpc}far;{$endif}
begin
Pvarsym(sym)^.definition^.get_rtti_label;
end;
procedure Trecorddef.write_child_rtti_data;
begin
symtable^.foreach({$ifndef TP}@{$endif}generate_child_rtti);
end;
procedure Trecorddef.write_child_init_data;
begin
symtable^.foreach({$ifndef TP}@{$endif}generate_child_inittable);
end;
procedure Trecorddef.write_rtti_data;
begin
rttilist^.concat(new(pai_const,init_8bit(tkrecord)));
write_rtti_name;
rttilist^.concat(new(pai_const,init_32bit(size)));
count:=0;
symtable^.foreach({$ifndef TP}@{$endif}count_fields);
rttilist^.concat(new(pai_const,init_32bit(count)));
symtable^.foreach({$ifndef TP}@{$endif}write_field_rtti);
end;
procedure Trecorddef.write_init_data;
begin
rttilist^.concat(new(pai_const,init_8bit(14)));
write_rtti_name;
rttilist^.concat(new(pai_const,init_32bit(size)));
count:=0;
symtable^.foreach({$ifndef TP}@{$endif}count_inittable_fields);
rttilist^.concat(new(pai_const,init_32bit(count)));
symtable^.foreach({$ifndef TP}@{$endif}write_field_inittable);
end;
function Trecorddef.gettypename:string;
begin
gettypename:='<record type>'
end;
{***************************************************************************
Tstringprocdef
***************************************************************************}
constructor Tstringdef.shortinit(l:byte;Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
string_typ:=st_shortstring;
len:=l;
savesize:=len+1;
end;
constructor Tstringdef.shortload(var s:Tstream);
begin
inherited load(s);
string_typ:=st_shortstring;
{ len:=readbyte;
savesize:=len+1;}
end;
constructor Tstringdef.longinit(l:longint;Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
string_typ:=st_longstring;
len:=l;
savesize:=target_os.size_of_pointer;
end;
constructor Tstringdef.longload(var s:Tstream);
begin
inherited load(s);
string_typ:=st_longstring;
{ len:=readlong;
savesize:=target_os.size_of_pointer;}
end;
constructor tstringdef.ansiinit(l:longint;Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
include(properties,dp_ret_in_acc);
string_typ:=st_ansistring;
len:=l;
savesize:=target_os.size_of_pointer;
end;
constructor Tstringdef.ansiload(var s:Tstream);
begin
inherited load(s);
string_typ:=st_ansistring;
{ len:=readlong;
savesize:=target_os.size_of_pointer;}
end;
constructor Tstringdef.wideinit(l:longint;Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
include(properties,dp_ret_in_acc);
string_typ:=st_widestring;
len:=l;
savesize:=target_os.size_of_pointer;
end;
constructor Tstringdef.wideload(var s:Tstream);
begin
inherited load(s);
string_typ:=st_widestring;
{ len:=readlong;
savesize:=target_os.size_of_pointer;}
end;
function Tstringdef.stringtypname:string;
const typname:array[tstringtype] of string[8]=
('','SHORTSTR','LONGSTR','ANSISTR','WIDESTR');
begin
stringtypname:=typname[string_typ];
end;
function tstringdef.size:longint;
begin
size:=savesize;
end;
procedure Tstringdef.store(var s:Tstream);
begin
inherited store(s);
{ if string_typ=st_shortstring then
writebyte(len)
else
writelong(len);
case string_typ of
st_shortstring:
current_ppu^.writeentry(ibshortstringdef);
st_longstring:
current_ppu^.writeentry(iblongstringdef);
st_ansistring:
current_ppu^.writeentry(ibansistringdef);
st_widestring:
current_ppu^.writeentry(ibwidestringdef);
end;}
end;
{$ifdef GDB}
function tstringdef.stabstring : pchar;
var
bytest,charst,longst : string;
begin
case string_typ of
st_shortstring:
begin
charst := typeglobalnumber('char');
{ this is what I found in stabs.texinfo but
gdb 4.12 for go32 doesn't understand that !! }
{$IfDef GDBknowsstrings}
stabstring := strpnew('n'+charst+';'+tostr(len));
{$else}
bytest := typeglobalnumber('byte');
stabstring := strpnew('s'+tostr(len+1)+'length:'+bytest
+',0,8;st:ar'+bytest
+';1;'+tostr(len)+';'+charst+',8,'+tostr(len*8)+';;');
{$EndIf}
end;
st_longstring:
begin
charst := typeglobalnumber('char');
{ this is what I found in stabs.texinfo but
gdb 4.12 for go32 doesn't understand that !! }
{$IfDef GDBknowsstrings}
stabstring := strpnew('n'+charst+';'+tostr(len));
{$else}
bytest := typeglobalnumber('byte');
longst := typeglobalnumber('longint');
stabstring := strpnew('s'+tostr(len+5)+'length:'+longst
+',0,32;dummy:'+bytest+',32,8;st:ar'+bytest
+';1;'+tostr(len)+';'+charst+',40,'+tostr(len*8)+';;');
{$EndIf}
end;
st_ansistring:
begin
{ an ansi string looks like a pchar easy !! }
stabstring:=strpnew('*'+typeglobalnumber('char'));
end;
st_widestring:
begin
{ an ansi string looks like a pchar easy !! }
stabstring:=strpnew('*'+typeglobalnumber('char'));
end;
end;
end;
procedure tstringdef.concatstabto(asmlist : paasmoutput);
begin
inherited concatstabto(asmlist);
end;
{$endif GDB}
function tstringdef.needs_inittable : boolean;
begin
needs_inittable:=string_typ in [st_ansistring,st_widestring];
end;
function tstringdef.gettypename : string;
const
names : array[tstringtype] of string[20] = ('',
'ShortString','LongString','AnsiString','WideString');
begin
gettypename:=names[string_typ];
end;
procedure tstringdef.write_rtti_data;
begin
case string_typ of
st_ansistring:
begin
rttilist^.concat(new(pai_const,init_8bit(tkAString)));
write_rtti_name;
end;
st_widestring:
begin
rttilist^.concat(new(pai_const,init_8bit(tkWString)));
write_rtti_name;
end;
st_longstring:
begin
rttilist^.concat(new(pai_const,init_8bit(tkLString)));
write_rtti_name;
end;
st_shortstring:
begin
rttilist^.concat(new(pai_const,init_8bit(tkSString)));
write_rtti_name;
rttilist^.concat(new(pai_const,init_8bit(len)));
end;
end;
end;
function tstringdef.is_publishable : boolean;
begin
is_publishable:=true;
end;
{***************************************************************************
Tabstractprocdef
***************************************************************************}
constructor Tabstractprocdef.init(Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
include(properties,dp_ret_in_acc);
retdef:=voiddef;
savesize:=target_os.size_of_pointer;
end;
constructor Tabstractprocdef.load(var s:Tstream);
var count,i:word;
begin
inherited load(s);
(* retdef:=readdefref;
fpu_used:=readbyte;
options:=readlong;
count:=readword;
new(parameters);
savesize:=target_os.size_of_pointer;
for i:=1 to count do
parameters^.readsymref;*)
end;
{ all functions returning in FPU are
assume to use 2 FPU registers
until the function implementation
is processed PM }
procedure Tabstractprocdef.test_if_fpu_result;
begin
if (retdef<>nil) and (typeof(retdef^)=typeof(Tfloatdef)) and
(Pfloatdef(retdef)^.typ in [f32bit,f16bit]) then
fpu_used:=2;
end;
procedure Tabstractprocdef.deref;
var i:longint;
begin
inherited deref;
{ resolvedef(retdef);}
for i:=0 to parameters^.count-1 do
Psym(parameters^.at(i))^.deref;
end;
function Tabstractprocdef.para_size:longint;
var i,l:longint;
begin
l:=0;
for i:=0 to parameters^.count-1 do
inc(l,Pparamsym(parameters^.at(i))^.getpushsize);
para_size:=l;
end;
procedure Tabstractprocdef.store(var s:Tstream);
var count,i:word;
begin
inherited store(s);
{ writedefref(retdef);
current_ppu^.do_interface_crc:=false;
writebyte(fpu_used);
writelong(options);
writeword(parameters^.count);
for i:=0 to parameters^.count-1 do
begin
writebyte(byte(hp^.paratyp));
writesymfref(hp^.data);
end;}
end;
function Tabstractprocdef.demangled_paras:string;
var i:longint;
s:string;
procedure doconcat(p:Pparameter);
begin
s:=s+p^.data^.name;
if p^.paratyp=vs_var then
s:=s+'var'
else if p^.paratyp=vs_const then
s:=s+'const';
end;
begin
s:='(';
for i:=0 to parameters^.count-1 do
doconcat(parameters^.at(i));
s[length(s)]:=')';
demangled_paras:=s;
end;
destructor Tabstractprocdef.done;
begin
dispose(parameters,done);
inherited done;
end;
{***************************************************************************
TPROCDEF
***************************************************************************}
constructor Tprocdef.init(Aowner:Pcontainingsymtable);
begin
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tabstractprocdef));{$ENDIF}
fileinfo:=aktfilepos;
vmt_index:=-1;
new(localst,init);
if (cs_browser in aktmoduleswitches) and make_ref then
begin
new(references,init(2*owner^.index_growsize,
owner^.index_growsize));
references^.insert(new(Pref,init(tokenpos)));
end;
{First, we assume that all registers are used }
usedregisters:=[low(Tregister)..high(Tregister)];
forwarddef:=true;
end;
constructor Tprocdef.load(var s:Tstream);
var a:string;
begin
inherited load(s);
(* usedregisters:=readlong;
a:=readstring;
setstring(_mangledname,s);
extnumber:=readlong;
nextoerloaded:=pprocdef(readdefref);
_class := pobjectdef(readdefref);
readposinfo(fileinfo);
if (cs_link_deffile in aktglobalswitches)
and (poexports in options) then
deffile.ddexport(mangledname);
count:=true;*)
end;
const local_symtable_index : longint = $8001;
procedure tprocdef.load_references;
var pos:Tfileposinfo;
pdo:Pobjectdef;
move_last:boolean;
begin
(* move_last:=lastwritten=lastref;
while (not current_ppu^.endofentry) do
begin
readposinfo(pos);
inc(refcount);
lastref:=new(pref,init(lastref,@pos));
lastref^.is_written:=true;
if refcount=1 then
defref:=lastref;
end;
if move_last then
lastwritten:=lastref;
if ((current_module^.flags and uf_local_browser)<>0)
and is_in_current then
begin
{$ifndef NOLOCALBROWSER}
pdo:=_class;
new(parast,loadas(parasymtable));
parast^.next:=owner;
parast^.load_browser;
new(localst,loadas(localsymtable));
localst^.next:=parast;
localst^.load_browser;
{$endif NOLOCALBROWSER}
end;*)
end;
function Tprocdef.write_references:boolean;
var ref:Pref;
pdo:Pobjectdef;
move_last:boolean;
begin
(* move_last:=lastwritten=lastref;
if move_last and (((current_module^.flags and uf_local_browser)=0)
or not is_in_current) then
exit;
{Write address of this symbol }
writedefref(@self);
{Write refs }
if assigned(lastwritten) then
ref:=lastwritten
else
ref:=defref;
while assigned(ref) do
begin
if ref^.moduleindex=current_module^.unit_index then
begin
writeposinfo(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;
current_ppu^.writeentry(ibdefref);
write_references:=true;
if ((current_module^.flags and uf_local_browser)<>0)
and is_in_current then
begin
pdo:=_class;
if (owner^.symtabletype<>localsymtable) then
while assigned(pdo) do
begin
if pdo^.publicsyms<>aktrecordsymtable then
begin
pdo^.publicsyms^.unitid:=local_symtable_index;
inc(local_symtable_index);
end;
pdo:=pdo^.childof;
end;
{We need TESTLOCALBROWSER para and local symtables
PPU files are then easier to read PM.}
inc(local_symtable_index);
parast^.write_browser;
if not assigned(localst) then
localst:=new(psymtable,init);
localst^.writeas;
localst^.unitid:=local_symtable_index;
inc(local_symtable_index);
localst^.write_browser;
{Decrement for.}
local_symtable_index:=local_symtable_index-2;
pdo:=_class;
if (owner^.symtabletype<>localsymtable) then
while assigned(pdo) do
begin
if pdo^.publicsyms<>aktrecordsymtable then
dec(local_symtable_index);
pdo:=pdo^.childof;
end;
end;*)
end;
destructor Tprocdef.done;
begin
if po_msgstr in options then
strdispose(messageinf.str);
if references<>nil then
dispose(references,done);
if (localst<>nil) and (typeof(localst^)<>typeof(Timplsymtable)) then
dispose(localst,done);
{ if (poinline in options) and (code,nil) then
disposetree(ptree(code));}
if _mangledname<>nil then
disposestr(_mangledname);
inherited done;
end;
procedure Tprocdef.store(var s:Tstream);
begin
(* inherited store(s);
current_ppu^.do_interface_crc:=false;
writelong(usedregisters);
writestring(mangledname);
current_ppu^.do_interface_crc:=true;
writelong(extnumber);
if (options and pooperator) = 0 then
writedefref(nextoverloaded)
else
begin
{Only write the overloads from the same unit }
if assigned(nextoverloaded) and
(nextoverloaded^.owner=owner) then
writedefref(nextoverloaded)
else
writedefref(nil);
end;
writedefref(_class);
writeposinfo(fileinfo);
if (poinline and options) then
begin
{We need to save
- the para and the local symtable
- the code ptree !! PM
writesymtable(parast);
writesymtable(localst);
writeptree(ptree(code));
}
end;
current_ppu^.writeentry(ibprocdef);*)
end;
procedure Tprocdef.deref;
begin
{ inherited deref;
resolvedef(pdef(nextoverloaded));
resolvedef(pdef(_class));}
end;
function Tprocdef.mangledname:string;
var i:word;
a:byte;
s:Pprocsym;
r:string;
begin
if _mangledname<>nil then
mangledname:=_mangledname^
else
begin
{If the procedure is in a unit, we start with the unitname.}
if current_module^.is_unit then
r:='_'+current_module^.modulename^
else
r:='';
a:=length(r);
{If we are a method we add the name of the object we are
belonging to.}
if (Pprocsym(sym)^._class<>nil) then
r:=r+'_M'+Pprocsym(sym)^._class^.sym^.name+'_M';
{Then we add the names of the procedures we are defined in
(for the case we are a nested procedure).}
s:=Pprocsym(sym)^.sub_of;
while typeof(s^.owner^)=typeof(Tprocsymtable) do
begin
insert('_$'+s^.name,r,a);
s:=s^.sub_of;
end;
r:=r+'_'+sym^.name;
{Add the types of all parameters.}
for i:=0 to parameters^.count-1 do
begin
r:=r+'$'+Pparameter(parameters^.at(i))^.data^.name;
end;
end;
end;
procedure Tprocdef.setmangledname(const s:string);
begin
if _mangledname<>nil then
disposestr(_mangledname);
_mangledname:=stringdup(s);
if localst<>nil then
begin
stringdispose(localst^.name);
localst^.name:=stringdup('locals of '+s);
end;
end;
{***************************************************************************
Tprocvardef
***************************************************************************}
{$IFDEF TP}
constructor Tprocvardef.init(Aowner:Pcontainingsymtable);
begin
setparent(typeof(Tabstractprocdef));
end;
{$ENDIF TP}
function Tprocvardef.size:longint;
begin
if po_methodpointer in options then
size:=2*target_os.size_of_pointer
else
size:=target_os.size_of_pointer;
end;
{$ifdef GDB}
function tprocvardef.stabstring : pchar;
var
nss : pchar;
i : word;
param : pdefcoll;
begin
i := 0;
param := para1;
while assigned(param) do
begin
inc(i);
param := param^.next;
end;
getmem(nss,1024);
{ it is not a function but a function pointer !! (PM) }
strpcopy(nss,'*f'+retdef^.numberstring{+','+tostr(i)}+';');
param := para1;
i := 0;
{ this confuses gdb !!
we should use 'F' instead of 'f' but
as we use c++ language mode
it does not like that either
Please do not remove this part
might be used once
gdb for pascal is ready PM }
(* while assigned(param) do
begin
inc(i);
if param^.paratyp = vs_value then vartyp := '1' else vartyp := '0';
{Here we have lost the parameter names !!}
pst := strpnew('p'+tostr(i)+':'+param^.data^.numberstring+','+vartyp+';');
strcat(nss,pst);
strdispose(pst);
param := param^.next;
end; *)
{strpcopy(strend(nss),';');}
stabstring := strnew(nss);
freemem(nss,1024);
end;
procedure tprocvardef.concatstabto(asmlist : paasmoutput);
begin
if ( not assigned(sym) or sym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
and not is_def_stab_written then
inherited concatstabto(asmlist);
is_def_stab_written:=true;
end;
{$endif GDB}
procedure Tprocvardef.write_rtti_data;
begin
{!!!!!!!}
end;
procedure Tprocvardef.write_child_rtti_data;
begin
{!!!!!!!!}
end;
function Tprocvardef.is_publishable:boolean;
begin
is_publishable:=po_methodpointer in options;
end;
function Tprocvardef.gettypename:string;
begin
gettypename:='<procedure variable type>'
end;
{****************************************************************************
Tforwarddef
****************************************************************************}
constructor tforwarddef.init(Aowner:Pcontainingsymtable;
const s:string;const pos:Tfileposinfo);
var oldregisterdef:boolean;
begin
{ never register the forwarddefs, they are disposed at the
end of the type declaration block }
{ oldregisterdef:=registerdef;
registerdef:=false;}
inherited init(Aowner);
{$IFDEF TP}setparent(typeof(Tdef));{$ENDIF}
{ registerdef:=oldregisterdef;}
tosymname:=s;
forwardpos:=pos;
end;
function tforwarddef.gettypename:string;
begin
gettypename:='unresolved forward to '+tosymname;
end;
end.
{
$Log$
Revision 1.6 2000-03-16 12:52:47 daniel
* Changed names of procedures flags
* Changed VMT generation
Revision 1.5 2000/03/11 21:11:24 daniel
* Ported hcgdata to new symtable.
* Alignment code changed as suggested by Peter
+ Usage of my is operator replacement, is_object
Revision 1.4 2000/03/01 11:43:55 daniel
* Some more work on the new symtable.
+ Symtable stack unit 'symstack' added.
}