Browse Source

+ Brand new symtable:
+ Less memory usage
+ Less code
- No debug information yet
- No unit support yet

daniel 26 years ago
parent
commit
590de0e5d7

+ 2546 - 0
compiler/new/symtable/defs.pas

@@ -0,0 +1,2546 @@
+{
+    $Id$
+
+    This unit handles definitions
+
+    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 defs;
+
+interface
+
+uses    symtable,objects,cobjects,symtablt,globtype
+{$ifdef i386}
+        ,i386base
+{$endif}
+{$ifdef m68k}
+        ,m68k
+{$endif}
+{$ifdef alpha}
+        ,alpha
+{$endif};
+
+type    Targconvtyp=(act_convertable,act_equal,act_exact);
+
+        Tvarspez=(vs_value,vs_const,vs_var);
+
+        Tobjprop=(sp_public,sp_private,sp_protected,
+                  sp_forwarddef,sp_static);
+        Tobjpropset=set of Tobjprop;
+
+        Tobjoption=(oo_is_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_has_private,         {The object has private members.}
+                    oo_has_protected,       {The obejct has protected
+                                             members.}
+                    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.}
+                    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;
+
+        {Options for Tprocdef and Tprocvardef}
+        Tprocoption=(povirtualmethod,   {Procedure is a virtual method.}
+                     poclearstack,      {Use IBM flat calling convention.
+                                         (Used by GCC.)}
+                     poconstructor,     {Procedure is a constructor.}
+                     podestructor,      {Procedure is a destructor.}
+                     pointernproc,      {Procedure has compiler magic.}
+                     poexports,         {Procedure is exported.}
+                     poiocheck,         {IO checking should be done after
+                                         a call to the procedure.}
+                     poabstractmethod,  {Procedure is an abstract method.}
+                     pointerrupt,       {Procedure is an interrupt handler.}
+                     poinline,          {Procedure is an assembler macro.}
+                     poassembler,       {Procedure is written in assembler.}
+                     pooperator,        {Procedure defines an operator.}
+                     poexternal,        {Procedure is external (in other
+                                         object or lib)}
+                     poleftright,       {Push parameters from left to right.}
+                     poprocinit,        {Program initialization.}
+                     postaticmethod,    {Static method.}
+                     pooveridingmethod, {Method with override directive }
+                     poclassmethod,     {Class method.}
+                     pounitinit,        {Unit initialization }
+                     pomethodpointer,   {Method pointer, only in procvardef,
+                                         also used for 'with object do' }
+                     pocdecl,           {Procedure uses C styled calling }
+                     popalmossyscall,   {Procedure is a PalmOS system call }
+                     pointernconst,     {Procedure has constant evaluator
+                                         intern.}
+                     poregister,        {Procedure uses register (fastcall)
+                                         calling }
+                     pounitfinalize,    {Unit finalization }
+                     postdcall,         {Procedure uses stdcall
+                                         call.}
+                     pomsgstr,          {Method for string message
+                                         handling.}
+                     pomsgint,          {Method for int message handling.}
+                     posavestdregs,     {Save std regs cdecl and stdcall
+                                         need that !}
+                     pocontainsself,    {Self is passed explicit to the
+                                         compiler.}
+                     posafecall);       {Safe call calling conventions }
+        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;
+            typed_as: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 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 GDB}
+            function stabstring : pchar;virtual;
+            procedure concatstabto(asmlist : paasmoutput);virtual;
+{$endif GDB}
+            function gettypename:string;virtual;
+        end;
+
+        Pobjectdef=^Tobjectdef;
+        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;
+            constructor init(const n:string;Aowner:Pcontainingsymtable;
+                             parent:Pobjectdef);
+            constructor load(var s:Tstream);
+            procedure check_forwards;
+            procedure insertvmt;
+            function isrelated(d:Pobjectdef):boolean;
+            function search(const s:string):Psym;
+            function speedsearch(const s:string;
+                                 speedvalue:longint):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 { uwchar,bool1bit,bitfield},
+                   u64bit,s64bitint);
+
+        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)
+            setof: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;
+
+        Pabstractprocdef=^Pabstractprocdef;
+        Tabstractprocdef=object(Tdef)
+            {Saves a definition to the return type }
+            retdef:Pdef;
+            fpu_used:byte;              {How many stack fpu must be empty.}
+            options:Tprocoptionset;     {Save the procedure options.}
+            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;
+
+        Pprocvardef=^Pprocvardef;
+        Tprocvardef=object(Tabstractprocdef)
+            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;
+
+        Pprocdef = ^Tprocdef;
+        Tprocdef = object(tabstractprocdef)
+           objprop:Tobjpropset;
+           extnumber:longint;
+           { 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;
+           { 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;
+
+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.}
+
+implementation
+
+uses    systems,symbols,verbose,globals,aasm,files;
+
+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);
+    filetype:=ft;
+    typed_as:=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 '+typed_as^.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);
+    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
+****************************************************************************}
+
+function Terrordef.gettypename:string;
+
+begin
+    gettypename:='<erroneous type>';
+end;
+
+{****************************************************************************
+                             Tabstractpointerdef
+****************************************************************************}
+
+constructor Tabstractpointerdef.init(Aowner:Pcontainingsymtable;def:Pdef);
+
+begin
+    inherited init(Aowner);
+    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);
+   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
+****************************************************************************}
+
+function Tclassrefdef.gettypename:string;
+
+begin
+   gettypename:='Class of '+definition^.typename;
+end;
+
+{***************************************************************************
+                              TOBJECTDEF
+***************************************************************************}
+
+constructor Tobjectdef.init(const n:string;Aowner:Pcontainingsymtable;
+                            parent:Pobjectdef);
+
+begin
+    inherited init(Aowner);
+    new(publicsyms,init);
+    publicsyms^.name:=stringdup(n);
+    publicsyms^.defowner:=@self;
+    set_parent(parent);
+    objname:=stringdup(n);
+end;
+
+
+procedure tobjectdef.set_parent(parent:Pobjectdef);
+
+const   inherited_options=[oo_has_virtual,oo_has_private,oo_has_protected,
+                           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_vmt 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_vmt,oo_is_class]*parent^.options<>[] then
+                        begin
+                            vmt_offset:=parent^.vmt_offset;
+                            include(options,oo_has_vmt);
+                        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;
+
+begin
+    if oo_has_vmt in options then
+        internalerror($990803)
+    else
+        begin
+            {First round up to aktpakrecords.}
+            publicsyms^.datasize:=align(publicsyms^.datasize,
+             aktpackrecords);
+            vmt_offset:=publicsyms^.datasize;
+            publicsyms^.datasize:=publicsyms^.datasize+
+             target_os.size_of_pointer;
+            include(options,oo_has_vmt);
+        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.isrelated(d:Pobjectdef):boolean;
+
+var hp:Pobjectdef;
+
+begin
+    hp:=@self;
+    isrelated:=false;
+    while assigned(hp) do
+        begin
+            if hp=d then
+                begin
+                    isrelated:=true;
+                    break;
+                end;
+            hp:=hp^.childof;
+        end;
+end;
+
+function Tobjectdef.search(const s:string):Psym;
+
+begin
+    search:=speedsearch(s,getspeedvalue(s));
+end;
+
+function Tobjectdef.speedsearch(const s:string;speedvalue:longint):Psym;
+
+var r:Psym;
+
+begin
+    r:=publicsyms^.speedsearch(s,speedvalue);
+    if (r=nil) and (privatesyms<>nil) then
+        r:=privatesyms^.speedsearch(s,speedvalue);
+    if (r=nil) 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 oo_has_vmt 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;
+
+begin
+    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 (typeof(sym^)=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(sym:Psym;def:Pdef;shiftvalue:byte);
+
+var typvalue:byte;
+
+begin
+    if not(assigned(sym)) then
+        begin
+            rttilist^.concat(new(pai_const,init_32bit(1)));
+            typvalue:=3;
+        end
+    else if typeof(sym^)=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)^.readaccesssym,ppropertysym(sym)^.readaccessdef,0);
+            writeproc(Ppropertysym(sym)^.writeaccesssym,ppropertysym(sym)^.writeaccessdef,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)^.storedsym,ppropertysym(sym)^.storeddef,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);
+    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_smartlink 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_smartlink in aktmoduleswitches) then
+                datasegment^.concat(new(pai_symbol,
+                 initname_global(getrangecheckstring)))
+            else
+                datasegment^.concat(new(pai_symbol,
+                 initname(getrangecheckstring)));
+            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);
+    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_smartlink 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_smartlink in aktmoduleswitches) then
+          datasegment^.concat(new(pai_symbol,initname_global(getrangecheckstring)))
+        else
+          datasegment^.concat(new(pai_symbol,initname(getrangecheckstring)));
+        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);
+    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_smartlink 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_smartlink in aktmoduleswitches) then
+              datasegment^.concat(new(Pai_symbol,
+               initname_global(getrangecheckstring)))
+            else
+              datasegment^.concat(new(Pai_symbol,
+               initname(getrangecheckstring)));
+            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');
+
+begin
+    gettypename:=names[typ];
+end;
+
+{****************************************************************************
+                                Tfloatdef
+****************************************************************************}
+
+constructor Tfloatdef.init(t:Tfloattype;Aowner:Pcontainingsymtable);
+
+begin
+    inherited init(Aowner);
+    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);
+    setof:=s;
+    if high<32 then
+        begin
+            settype:=smallset;
+            savesize:=4;
+        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(setof^.get_rtti_label)));
+end;
+
+
+procedure Tsetdef.write_child_rtti_data;
+
+begin
+    setof^.get_rtti_label;
+end;
+
+
+function Tsetdef.is_publishable:boolean;
+
+begin
+    is_publishable:=settype=smallset;
+end;
+
+function Tsetdef.gettypename:string;
+
+begin
+   gettypename:='set of '+setof^.typename;
+end;
+{***************************************************************************
+                                  Trecorddef
+***************************************************************************}
+
+constructor Trecorddef.init(s:Precordsymtable;Aowner:Pcontainingsymtable);
+
+begin
+    inherited init(Aowner);
+    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;
+
+{***************************************************************************
+                            Tabstractprocdef
+***************************************************************************}
+
+constructor Tabstractprocdef.init(Aowner:Pcontainingsymtable);
+
+begin
+    inherited init(Aowner);
+    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);
+    fileinfo:=aktfilepos;
+    extnumber:=-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 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
+***************************************************************************}
+
+
+function Tprocvardef.size:longint;
+
+begin
+    if pomethodpointer 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:=pomethodpointer in options;
+end;
+
+function Tprocvardef.gettypename:string;
+
+begin
+   gettypename:='<procedure variable type>'
+end;
+
+end.

+ 1418 - 0
compiler/new/symtable/symbols.pas

@@ -0,0 +1,1418 @@
+ {
+    $Id$
+
+    This unit handles symbols
+
+    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 symbols;
+
+interface
+
+uses    symtable,aasm,objects,cobjects,defs
+{$ifdef i386}
+        ,i386base
+{$endif}
+{$ifdef m68k}
+        ,m68k
+{$endif}
+{$ifdef alpha}
+        ,alpha
+{$endif};
+
+{Note: It is forbidden to add the symtablt unit. A symbol should not now in
+ which symtable it is.}
+
+type    Ttypeprop=(sp_primary_typesym);
+        Ttypepropset=set of Ttypeprop;
+
+        Tpropprop=(ppo_indexed,ppo_defaultproperty,
+                   ppo_stored,ppo_published);
+        Tproppropset=set of Tpropprop;
+
+        Tvarprop=(vo_regable,vo_is_C_var,vo_is_external,vo_is_dll_var,
+                  vo_is_thread_var);
+        Tvarpropset=set of Tvarprop;
+
+
+        Plabelsym=^Tlabelsym;
+        Tlabelsym=object(Tsym)
+            lab:Pasmlabel;
+            defined:boolean;
+            constructor init(const n:string;l:Pasmlabel);
+            constructor load(var s:Tstream);
+            function mangledname:string;virtual;
+            procedure store(var s:Tstream);virtual;
+        end;
+
+{       Punitsym=^Tunitsym;
+        Tunitsym=object(Tsym)
+            unitsymtable : punitsymtable;
+            prevsym : punitsym;
+            refs : longint;
+            constructor init(const n : string;ref : punitsymtable);
+            constructor load(var s:Tstream);
+            destructor done;virtual;
+            procedure store(var s:Tstream);virtual;
+        end;}
+
+        Perrorsym=^Terrorsym;
+        Terrorsym=object(tsym)
+            constructor init;
+        end;
+
+        Pprocsym=^Tprocsym;
+        Tprocsym=object(Tsym)
+            definitions:Pobject;    {Is Pprocdef when procedure not
+                                     overloaded, or a Pcollection of
+                                     Pprocdef when it is overloaded.
+                                     Since most procedures are not
+                                     overloaded, this saves a lot of
+                                     memory.}
+            sub_of:Pprocsym;
+            _class:Pobjectdef;
+            constructor init(const n:string;Asub_of:Pprocsym);
+            constructor load(var s:Tstream);
+            procedure foreach(action:pointer);
+            procedure insert(def:Pdef);
+            function mangledname:string;virtual; {Causes internalerror.}
+            {Writes all declarations.}
+            procedure write_parameter_lists;
+            {Tests, if all procedures definitions are defined and not
+             just available as forward,}
+            procedure check_forward;
+            procedure store(var s:Tstream);virtual;
+            procedure deref;virtual;
+            procedure load_references;virtual;
+            function  write_references:boolean;virtual;
+            destructor done;virtual;
+        end;
+
+        Ptypesym=^Ttypesym;
+        Ttypesym=object(Tsym)
+            definition:Pdef;
+            forwardpointers:Pcollection;    {Contains the forwardpointers.}
+            properties:Ttypepropset;
+            synonym:Ptypesym;
+            constructor init(const n:string;d:Pdef);
+            constructor load(var s:Tstream);
+{           procedure addforwardpointer(p:Ppointerdef);}
+            procedure deref;virtual;
+            procedure store(var s:Tstream);virtual;
+            procedure load_references;virtual;
+            procedure updateforwarddef(p:pdef);
+            function  write_references:boolean;virtual;
+            destructor done;virtual;
+        end;
+
+        Psyssym=^Tsyssym;
+        Tsyssym=object(Tsym)
+            number:longint;
+            constructor init(const n:string;l:longint);
+            constructor load(var s:Tstream);
+            procedure store(var s:Tstream);virtual;
+        end;
+
+        Pmacrosym=^Tmacrosym;
+        Tmacrosym=object(Tsym)
+            defined:boolean;
+            buftext:Pchar;
+            buflen:longint;
+            {Macros aren't written to PPU files !}
+            constructor init(const n:string);
+            destructor done;virtual;
+        end;
+
+        Penumsym=^Tenumsym;
+        Tenumsym=object(tsym)
+            value:longint;
+            definition:Penumdef;
+            nextenum:Penumsym;
+            constructor init(const n:string;def:Penumdef;v:longint);
+            constructor load(var s:Tstream);
+            procedure store(var s:Tstream);virtual;
+            procedure deref;virtual;
+            procedure order;
+        end;
+
+        Pprogramsym=^Tprogramsym;
+        Tprogramsym=object(Tsym)
+        end;
+
+        Pvarsym=^Tvarsym;
+        Tvarsym=object(tsym)
+            address:longint;
+            localvarsym:Pvarsym;
+            islocalcopy:boolean;
+            definition:Pdef;
+            refs:longint;
+            properties:Tvarpropset;
+            objprop:Tobjpropset;
+            _mangledname:Pstring;
+            reg:Tregister;  {If reg<>R_NO, then the variable is an register
+                             variable }
+            constructor init(const n:string;p:Pdef);
+            constructor init_dll(const n:string;p:Pdef);
+            constructor init_C(const n,mangled:string;p:Pdef);
+            constructor load(var s:Tstream);
+            procedure concatdata(const n:string;len:longint);
+            procedure deref;virtual;
+            function getsize:longint;virtual;
+            function mangledname:string;virtual;
+            procedure insert_in_data;virtual;
+            procedure setmangledname(const s:string);
+            procedure store(var s:Tstream);virtual;
+            destructor done;virtual;
+        end;
+
+        Pparamsym=^Tparamsym;
+        Tparamsym=object(Tvarsym)
+            varspez:Tvarspez;
+            pushaddress:longint;
+            constructor init(const n:string;p:Pdef;vs:Tvarspez);
+            function getsize:longint;virtual;
+            function getpushsize:longint;virtual;
+            procedure insert_in_data;virtual;
+        end;
+
+        Ptypedconstsym=^Ttypedconstsym;
+        Ttypedconstsym=object(Tsym)
+            prefix:Pstring;
+            definition:Pdef;
+            is_really_const:boolean;
+            constructor init(const n:string;p:Pdef;really_const:boolean);
+            constructor load(var s:Tstream);
+            destructor done;virtual;
+            function mangledname:string;virtual;
+            procedure store(var s:Tstream);virtual;
+            procedure deref;virtual;
+            function getsize:longint;
+            procedure insert_in_data;virtual;
+        end;
+
+        Tconsttype=(constord,conststring,constreal,constbool,
+                    constint,constchar,constset,constnil);
+
+        Pconstsym=^Tconstsym;
+        Tconstsym=object(Tsym)
+           definition:Pdef;
+           consttype:Tconsttype;
+           value,len:longint;   {Len is needed for string length.}
+           constructor init(const n:string;t:Tconsttype;v:longint);
+           constructor init_def(const n:string;t:Tconsttype;v:longint;
+                                def:Pdef);
+           constructor init_string(const n:string;t:Tconsttype;
+                                   str:Pchar;l:longint);
+           constructor load(var s:Tstream);
+           procedure deref;virtual;
+           procedure store(var s:Tstream);virtual;
+           destructor done;virtual;
+        end;
+
+        absolutetyp = (tovar,toasm,toaddr);
+
+        Pabsolutesym = ^tabsolutesym;
+        Tabsolutesym = object(tvarsym)
+            abstyp:absolutetyp;
+            absseg:boolean;
+            ref:Psym;
+            asmname:Pstring;
+            constructor load(var s:Tstream);
+            procedure deref;virtual;
+            function mangledname : string;virtual;
+            procedure store(var s:Tstream);virtual;
+        end;
+
+        Pfuncretsym=^Tfuncretsym;
+        Tfuncretsym=object(tsym)
+            funcretprocinfo : pointer{ should be pprocinfo};
+            funcretdef:Pdef;
+            address:longint;
+            constructor init(const n:string;approcinfo:pointer{pprocinfo});
+            constructor load(var s:Tstream);
+            procedure insert_in_data;virtual;
+            procedure store(var s:Tstream);virtual;
+            procedure deref;virtual;
+        end;
+
+        Ppropertysym=^Tpropertysym;
+        Tpropertysym=object(Tsym)
+            properties:Tproppropset;
+            definition:Pdef;
+            readaccesssym,writeaccesssym,storedsym:Psym;
+            readaccessdef,writeaccessdef,storeddef:Pdef;
+            index,default:longint;
+            constructor load(var s:Tstream);
+            function getsize:longint;virtual;
+            procedure store(var s:Tstream);virtual;
+            procedure deref;virtual;
+        end;
+
+var current_object_option:Tobjpropset;
+    current_type_option:Ttypepropset;
+
+implementation
+
+uses    callspec,verbose,globals,systems,globtype;
+
+{****************************************************************************
+                                 Tlabelsym
+****************************************************************************}
+
+constructor Tlabelsym.init(const n:string;l:Pasmlabel);
+
+begin
+    inherited init(n);
+    lab:=l;
+    defined:=false;
+end;
+
+constructor Tlabelsym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+    defined:=true;
+end;
+
+function Tlabelsym.mangledname:string;
+
+begin
+    mangledname:=lab^.name;
+end;
+
+procedure Tlabelsym.store(var s:Tstream);
+
+begin
+    inherited store(s);
+{   current_ppu^.writeentry(iblabelsym);}
+end;
+
+{****************************************************************************
+                                  Terrorsym
+****************************************************************************}
+
+constructor terrorsym.init;
+
+begin
+    inherited init('');
+end;
+{****************************************************************************
+                                  Tprocsym
+****************************************************************************}
+
+constructor Tprocsym.init(const n:string;Asub_of:Pprocsym);
+
+begin
+    inherited init(n);
+    sub_of:=Asub_of;
+end;
+
+constructor Tprocsym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+{   definition:=Pprocdef(readdefref);}
+end;
+
+procedure Tprocsym.foreach(action:pointer);
+
+begin
+    if definitions<>nil then
+        begin
+            if typeof(definitions^)=typeof(Tcollection) then
+                Pcollection(definitions)^.foreach(action)
+            else
+                callpointerlocal(action,previousframepointer,definitions);
+        end;
+end;
+
+procedure Tprocsym.insert(def:Pdef);
+
+var c:Pcollection;
+
+begin
+    if definitions=nil then
+        definitions:=def
+    else
+        if typeof(definitions^)=typeof(Tcollection) then
+            Pcollection(def)^.insert(def)
+        else
+            begin
+                c:=new(Pcollection,init(8,4));
+                c^.insert(definitions);
+                definitions:=c;
+            end;
+end;
+
+function Tprocsym.mangledname:string;
+
+begin
+    internalerror($99080201);
+end;
+
+procedure Tprocsym.write_parameter_lists;
+
+{var    p:Pprocdef;}
+
+begin
+(*  p:=definition;
+    while assigned(p) do
+        begin
+            {Force the error to be printed.}
+            verbose.message1(sym_b_param_list,name+p^.demangled_paras);
+            p:=p^.nextoverloaded;
+        end;*)
+end;
+
+procedure tprocsym.check_forward;
+
+{var    pd:Pprocdef;}
+
+begin
+(*  pd:=definition;
+    while assigned(pd) do
+        begin
+            if pd^.forwarddef then
+                begin
+                    if assigned(pd^._class) then
+                        messagepos1(fileinfo,sym_e_forward_not_resolved,
+                         pd^._class^.objname^+'.'+name+
+                         demangledparas(pd^.demangled_paras))
+                    else
+                        messagepos1(fileinfo,sym_e_forward_not_resolved,
+                         name+pd^.demangled_paras);
+                    {Turn futher error messages off.}
+                    pd^.forwarddef:=false;
+                end;
+
+                pd:=pd^.nextoverloaded;
+        end;*)
+end;
+
+
+procedure tprocsym.deref;
+
+{var    t:ttoken;
+    last:Pprocdef;}
+
+begin
+(*
+    resolvedef(pdef(definition));
+    if (definition^.options and pooperator) <> 0 then
+        begin
+            last:=definition;
+            while assigned(last^.nextoverloaded) do
+                last:=last^.nextoverloaded;
+            for t:=first_overloaded to last_overloaded do
+                if (name=overloaded_names[t]) then
+                    begin
+                        if assigned(overloaded_operators[t]) then
+                            last^.nextoverloaded:=overloaded_operators[t]^.definition;
+                        overloaded_operators[t]:=@self;
+                    end;
+        end;*)
+end;
+
+procedure Tprocsym.store(var s:Tstream);
+
+begin
+    inherited store(s);
+{   writedefref(pdef(definition));
+    current_ppu^.writeentry(ibprocsym);}
+end;
+
+
+procedure tprocsym.load_references;
+
+begin
+    inherited load_references;
+end;
+
+function Tprocsym.write_references:boolean;
+
+{var    prdef:Pprocdef;}
+
+begin
+(*  write_references:=false;
+    if not inherited write_references then
+        exit;
+    write_references:=true;
+    prdef:=definition;
+    while assigned(prdef) and (prdef^.owner=definition^.owner) do
+        begin
+            prdef^.write_references;
+            prdef:=prdef^.nextoverloaded;
+        end;*)
+end;
+
+destructor Tprocsym.done;
+
+begin
+    {Don't check if errors !!}
+    if errorcount=0 then
+        check_forward;
+    inherited done;
+end;
+
+{****************************************************************************
+                                  Ttypesym
+****************************************************************************}
+
+constructor Ttypesym.init(const n:string;d:Pdef);
+
+begin
+    inherited init(n);
+    definition:=d;
+    if assigned(definition) then
+        begin
+            if definition^.sym<>nil then
+                begin
+                    definition^.sym:=@self;
+                    properties:=[sp_primary_typesym];
+                end
+            else
+                begin
+                    synonym:=Ptypesym(definition^.sym)^.synonym;
+                    Ptypesym(definition^.sym)^.synonym:=@self;
+                end;
+        end;
+end;
+
+constructor Ttypesym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+{   definition:=readdefref;}
+end;
+
+{procedure Ttypesym.addforwardpointer(p:Ppointerdef);
+
+begin
+    if forwardpointers=nil then
+        new(forwardpointers,init(8,4));
+    forwardpointers^.insert(p);
+end;}
+
+procedure ttypesym.deref;
+
+begin
+(*  resolvedef(definition);
+    if assigned(definition) then
+        begin
+            if properties=sp_primary_typesym then
+                begin
+                    if definition^.sym<>@self then
+                        synonym:=definition^.sym;
+                    definition^.sym:=@self;
+                end
+            else
+                begin
+                    if assigned(definition^.sym) then
+                        begin
+                            synonym:=definition^.sym^.synonym;
+                            if definition^.sym<>@self then
+                                definition^.sym^.synonym:=@self;
+                        end
+                    else
+                        definition^.sym:=@self;
+                end;
+            if (definition^.deftype=recorddef) and
+             assigned(precdef(definition)^.symtable) and
+             (definition^.sym=@self) then
+                precdef(definition)^.symtable^.name:=stringdup('record '+name);
+        end;*)
+end;
+
+
+procedure ttypesym.store(var s:Tstream);
+
+begin
+    inherited store(s);
+{   writedefref(definition);
+    current_ppu^.writeentry(ibtypesym);}
+end;
+
+
+procedure ttypesym.load_references;
+
+begin
+    inherited load_references;
+{   if typeof(definition^)=typeof(Trecorddef) then
+       Precdef(definition)^.symtable^.load_browser;
+    if typeof(definition^)=typeof(Tobjectdef) then
+       Pobjectdef(definition)^.publicsyms^.load_browser;}
+end;
+
+
+function ttypesym.write_references : boolean;
+
+begin
+(*  if not inherited write_references then
+    {Write address of this symbol if record or object
+     even if no real refs are there
+     because we need it for the symtable }
+    if (definition^.deftype=recorddef) or
+     (definition^.deftype=objectdef) then
+        begin
+            writesymref(@self);
+            current_ppu^.writeentry(ibsymref);
+        end;
+    write_references:=true;
+    if (definition^.deftype=recorddef) then
+        precdef(definition)^.symtable^.write_browser;
+    if (definition^.deftype=objectdef) then
+        pobjectdef(definition)^.publicsyms^.write_browser;*)
+end;
+
+
+procedure ttypesym.updateforwarddef(p:pdef);
+
+var i:word;
+
+begin
+    if definition<>nil then
+        internalerror($99080203)
+    else
+        definition:=p;
+    properties:=current_type_option;
+    fileinfo:=tokenpos;
+    if assigned(definition) and not(assigned(definition^.sym)) then
+        definition^.sym:=@self;
+    {Update all forwardpointers to this definition.}
+{   for i:=1 to forwardpointers^.count do
+        Ppointerdef(forwardpointers^.at(i))^.definition:=definition;}
+    forwardpointers^.deleteall;
+    dispose(forwardpointers,done);
+    forwardpointers:=nil;
+end;
+
+destructor Ttypesym.done;
+
+var prevsym:Ptypesym;
+
+begin
+    if assigned(definition) then
+        begin
+            prevsym:=Ptypesym(definition^.sym);
+            if prevsym=@self then
+                definition^.sym:=synonym;
+            while assigned(prevsym) do
+                begin
+                    if (prevsym^.synonym=@self) then
+                        begin
+                            prevsym^.synonym:=synonym;
+                            break;
+                     end;
+                    prevsym:=prevsym^.synonym;
+                end;
+           end;
+    synonym:=nil;
+    definition:=nil;
+    inherited done;
+end;
+
+{****************************************************************************
+                                  Tsyssym
+****************************************************************************}
+
+constructor Tsyssym.init(const n:string;l:longint);
+
+begin
+    inherited init(n);
+    number:=l;
+end;
+
+constructor Tsyssym.load(var s:Tstream);
+
+begin
+     inherited load(s);
+{    number:=readlong;}
+end;
+
+procedure tsyssym.store(var s:Tstream);
+
+begin
+    Tsym.store(s);
+{   writelong(number);
+    current_ppu^.writeentry(ibsyssym);}
+end;
+{****************************************************************************
+                                  Tenumsym
+****************************************************************************}
+
+constructor Tenumsym.init(const n:string;def:Penumdef;v:longint);
+
+begin
+    inherited init(n);
+    definition:=def;
+    value:=v;
+    if def^.minval>v then
+        def^.setmin(v);
+    if def^.maxval<v then
+        def^.setmax(v);
+    order;
+end;
+
+constructor Tenumsym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+{   definition:=Penumdef(readdefref);
+    value:=readlong;}
+end;
+
+procedure Tenumsym.deref;
+
+begin
+{   resolvedef(pdef(definition));
+    order;}
+end;
+
+procedure Tenumsym.order;
+
+var i:word;
+
+label   inserted;
+
+begin
+    {Keep the enum symbols ordered by value...}
+    with definition^.symbols^ do
+        begin
+            {Most of the time, enums are defined in order, so we count down.}
+            for i:=count-1 downto 0 do
+                begin
+                    if Penumsym(at(i))^.value<value then
+                        begin
+                            atinsert(i+1,@self);
+                            {We have to use goto to keep the
+                             code efficient :( }
+                            goto inserted;
+                        end;
+                end;
+            atinsert(0,@self);
+        inserted:
+        end;
+end;
+
+
+procedure Tenumsym.store(var s:Tstream);
+
+begin
+    inherited store(s);
+(*  writedefref(definition);
+    writelong(value);
+    current_ppu^.writeentry(ibenumsym);*)
+end;
+
+{****************************************************************************
+                                  Tmacrosym
+****************************************************************************}
+
+constructor Tmacrosym.init(const n:string);
+
+begin
+    inherited init(n);
+    defined:=true;
+end;
+
+destructor Tmacrosym.done;
+
+begin
+    if assigned(buftext) then
+        freemem(buftext,buflen);
+    inherited done;
+end;
+
+{****************************************************************************
+                                  Tprogramsym
+****************************************************************************}
+
+{****************************************************************************
+                                    Tvarsym
+****************************************************************************}
+
+
+constructor Tvarsym.init(const n:string;p:Pdef);
+
+begin
+    inherited init(n);
+    definition:=p;
+    {Can we load the value into a register ? }
+    if dp_regable in p^.properties then
+        include(properties,vo_regable);
+    reg:=R_NO;
+end;
+
+constructor Tvarsym.init_dll(const n:string;p:Pdef);
+
+begin
+    init(n,p);
+    include(properties,vo_is_dll_var);
+end;
+
+
+constructor Tvarsym.init_C(const n,mangled:string;p:Pdef);
+
+begin
+    init(n,p);
+    include(properties,vo_is_C_var);
+    setmangledname(mangled);
+end;
+
+procedure Tvarsym.concatdata(const n:string;len:longint);
+
+begin
+end;
+
+constructor Tvarsym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+    reg:=R_NO;
+{   if read_member then
+        address:=readlong
+    else
+        address:=0;
+    definition:=readdefref;
+    var_options:=readbyte;
+    if (var_options and vo_is_C_var)<>0 then
+        setmangledname(readstring);}
+end;
+
+function Tvarsym.getsize:longint;
+
+begin
+    if definition<>nil then
+        getsize:=definition^.size
+    else
+        getsize:=0;
+end;
+
+procedure Tvarsym.deref;
+
+begin
+{   resolvedef(definition);}
+end;
+
+
+procedure Tvarsym.store(var s:Tstream);
+
+begin
+(*  inherited store(s);
+    if read_member then
+        writelong(address);
+    writedefref(definition);
+    { symbols which are load are never candidates for a register,
+      turn of the regable }
+    writebyte(var_options and (not vo_regable));
+    if (var_options and vo_is_C_var)<>0 then
+        writestring(mangledname);
+    current_ppu^.writeentry(ibvarsym);*)
+end;
+
+
+procedure Tvarsym.setmangledname(const s:string);
+
+begin
+    _mangledname:=stringdup(s);
+end;
+
+
+function Tvarsym.mangledname:string;
+
+var prefix:string;
+
+begin
+    if assigned(_mangledname) then
+        mangledname:=_mangledname^
+    else
+        mangledname:=owner^.varsymprefix+name;
+end;
+
+procedure Tvarsym.insert_in_data;
+
+var l,ali,modulo:longint;
+    storefilepos:Tfileposinfo;
+
+begin
+    if (vo_is_external in properties) then
+        begin
+            {Handle static variables of objects especially }
+            if read_member and (sp_static in objprop) then
+                begin
+                    {The data field is generated in parser.pas
+                     with a tobject_FIELDNAME variable, so we do
+                     not need to do it in this procedure.}
+
+                    {This symbol can't be loaded to a register.}
+                    exclude(properties,vo_regable);
+                end
+            else
+                if not(read_member) then
+                    begin
+                        storefilepos:=aktfilepos;
+                        aktfilepos:=tokenpos;
+                        if (vo_is_thread_var in properties) then
+                            l:=4
+                        else
+                            l:=getsize;
+                        address:=owner^.varsymtodata(@self,l);
+                        aktfilepos:=storefilepos;
+                    end;
+        end;
+end;
+
+destructor Tvarsym.done;
+
+begin
+    disposestr(_mangledname);
+    inherited done;
+end;
+
+{****************************************************************************
+                                Tparamsym
+****************************************************************************}
+
+constructor Tparamsym.init(const n:string;p:Pdef;vs:Tvarspez);
+
+begin
+    inherited init(n,p);
+    varspez:=vs;
+end;
+
+function Tparamsym.getsize:longint;
+
+begin
+    if (definition<>nil) and (varspez=vs_value) then
+        getsize:=definition^.size
+    else
+        getsize:=0;
+end;
+
+function Tparamsym.getpushsize:longint;
+
+begin
+    if assigned(definition) then
+        begin
+            case varspez of
+                vs_var:
+                    getpushsize:=target_os.size_of_pointer;
+                vs_value,vs_const:
+                     if dp_pointer_param in definition^.properties then
+                         getpushsize:=target_os.size_of_pointer
+                     else
+                         getpushsize:=definition^.size;
+            end;
+        end
+    else
+        getpushsize:=0;
+end;
+
+procedure Tparamsym.insert_in_data;
+
+var storefilepos:Tfileposinfo;
+
+begin
+    storefilepos:=aktfilepos;
+    {Handle static variables of objects especially }
+    if read_member and (sp_static in objprop) then
+        begin
+            {The data field is generated in parser.pas
+             with a tobject_FIELDNAME variable, so we do
+             not need to do it in this procedure.}
+
+            {This symbol can't be loaded to a register.}
+            exclude(properties,vo_regable);
+        end
+    else
+        if not(read_member) then
+            pushaddress:=owner^.varsymtodata(@self,getpushsize);
+        if (varspez=vs_var) then
+            address:=0
+        else if (varspez=vs_value) then
+            if dp_pointer_param in definition^.properties then
+                begin
+                    {Allocate local space.}
+                    address:=owner^.datasize;
+                    inc(owner^.datasize,getsize);
+                end
+            else
+                address:=pushaddress
+        else
+            {vs_const}
+            if dp_pointer_param in definition^.properties then
+                address:=0
+            else
+                address:=pushaddress;
+    aktfilepos:=storefilepos;
+end;
+
+{****************************************************************************
+                             Ttypedconstsym
+*****************************************************************************}
+
+constructor Ttypedconstsym.init(const n:string;p:Pdef;really_const:boolean);
+
+begin
+   inherited init(n);
+   definition:=p;
+   is_really_const:=really_const;
+   prefix:=stringdup(procprefix);
+end;
+
+constructor Ttypedconstsym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+(*  definition:=readdefref;
+{$ifdef DELPHI_CONST_IN_RODATA}
+    is_really_const:=boolean(readbyte);
+{$else DELPHI_CONST_IN_RODATA}
+    is_really_const:=false;
+{$endif DELPHI_CONST_IN_RODATA}
+    prefix:=stringdup(readstring);*)
+end;
+
+procedure Ttypedconstsym.deref;
+
+begin
+{   resolvedef(definition);}
+end;
+
+function Ttypedconstsym.mangledname:string;
+
+begin
+    mangledname:='TC_'+prefix^+'_'+name;
+end;
+
+
+function Ttypedconstsym.getsize:longint;
+
+begin
+    if assigned(definition) then
+        getsize:=definition^.size
+    else
+        getsize:=0;
+end;
+
+procedure Ttypedconstsym.store(var s:Tstream);
+
+begin
+   inherited store(s);
+(*   writedefref(definition);
+   writestring(prefix^);
+{$ifdef DELPHI_CONST_IN_RODATA}
+   writebyte(byte(is_really_const));
+{$endif DELPHI_CONST_IN_RODATA}
+   current_ppu^.writeentry(ibtypedconstsym);*)
+end;
+
+{ for most symbol types ther is nothing to do at all }
+procedure Ttypedconstsym.insert_in_data;
+
+var constsegment:Paasmoutput;
+    l,ali,modulo:longint;
+    storefilepos:Tfileposinfo;
+
+begin
+    storefilepos:=aktfilepos;
+    aktfilepos:=tokenpos;
+    owner^.tconstsymtodata(@self,getsize);
+    aktfilepos:=storefilepos;
+end;
+
+destructor Ttypedconstsym.done;
+
+begin
+    stringdispose(prefix);
+    inherited done;
+end;
+
+{****************************************************************************
+                                  TCONSTSYM
+****************************************************************************}
+
+constructor Tconstsym.init(const n : string;t : tconsttype;v : longint);
+
+begin
+    inherited init(n);
+    consttype:=t;
+    value:=v;
+end;
+
+
+constructor Tconstsym.init_def(const n:string;t:Tconsttype;
+                               v:longint;def:Pdef);
+
+begin
+    inherited init(n);
+    consttype:=t;
+    value:=v;
+    definition:=def;
+end;
+
+
+constructor Tconstsym.init_string(const n:string;t:Tconsttype;str:Pchar;l:longint);
+
+begin
+    inherited init(n);
+    consttype:=t;
+    value:=longint(str);
+    len:=l;
+end;
+
+constructor Tconstsym.load(var s:Tstream);
+
+var pd:Pbestreal;
+    ps:Pnormalset;
+
+begin
+    inherited load(s);
+(*  consttype:=tconsttype(readbyte);
+    case consttype of
+      constint,
+      constbool,
+      constchar : value:=readlong;
+      constord :
+        begin
+          definition:=readdefref;
+          value:=readlong;
+        end;
+      conststring :
+        begin
+          len:=readlong;
+          getmem(pchar(value),len+1);
+          current_ppu^.getdata(pchar(value)^,len);
+        end;
+      constreal :
+        begin
+          new(pd);
+          pd^:=readreal;
+          value:=longint(pd);
+        end;
+      constset :
+        begin
+          definition:=readdefref;
+          new(ps);
+          readnormalset(ps^);
+          value:=longint(ps);
+        end;
+      constnil : ;
+      else
+        Message1(unit_f_ppu_invalid_entry,tostr(ord(consttype)));
+   end;*)
+end;
+
+procedure Tconstsym.deref;
+
+begin
+{   if consttype in [constord,constset] then
+        resolvedef(pdef(definition));}
+end;
+
+
+procedure Tconstsym.store(var s:Tstream);
+
+begin
+(*  inherited store(s);
+    writebyte(byte(consttype));
+    case consttype of
+      constnil : ;
+      constint,
+      constbool,
+      constchar :
+        writelong(value);
+      constord :
+        begin
+          writedefref(definition);
+          writelong(value);
+        end;
+      conststring :
+        begin
+          writelong(len);
+          current_ppu^.putdata(pchar(value)^,len);
+        end;
+      constreal :
+        writereal(pbestreal(value)^);
+      constset :
+        begin
+          writedefref(definition);
+          writenormalset(pointer(value)^);
+        end;
+    else
+      internalerror(13);
+    end;
+    current_ppu^.writeentry(ibconstsym);*)
+end;
+
+destructor Tconstsym.done;
+
+begin
+    case consttype of
+        conststring:
+            freemem(Pchar(value),len+1);
+        constreal:
+            dispose(Pbestreal(value));
+        constset:
+            dispose(Pnormalset(value));
+    end;
+    inherited done;
+end;
+
+{****************************************************************************
+                                Tabsolutesym
+****************************************************************************}
+
+constructor Tabsolutesym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+(*  typ:=absolutesym;
+    abstyp:=absolutetyp(readbyte);
+    case abstyp of
+      tovar :
+        begin
+          asmname:=stringdup(readstring);
+          ref:=srsym;
+        end;
+      toasm :
+        asmname:=stringdup(readstring);
+      toaddr :
+        begin
+          address:=readlong;
+          absseg:=boolean(readbyte);
+        end;
+    end;*)
+end;
+
+
+procedure tabsolutesym.store(var s:Tstream);
+
+begin
+    inherited store(s);
+(*  writebyte(byte(varspez));
+    if read_member then
+      writelong(address);
+    writedefref(definition);
+    writebyte(var_options and (not vo_regable));
+    writebyte(byte(abstyp));
+    case abstyp of
+      tovar :
+        writestring(ref^.name);
+      toasm :
+        writestring(asmname^);
+      toaddr :
+        begin
+          writelong(address);
+          writebyte(byte(absseg));
+        end;
+    end;
+    current_ppu^.writeentry(ibabsolutesym);*)
+end;
+
+
+procedure tabsolutesym.deref;
+
+begin
+(*  resolvedef(definition);
+    if (abstyp=tovar) and (asmname<>nil) then
+        begin
+            { search previous loaded symtables }
+            getsym(asmname^,false);
+            if not(assigned(srsym)) then
+            getsymonlyin(owner,asmname^);
+            if not(assigned(srsym)) then
+                srsym:=generrorsym;
+            ref:=srsym;
+            stringdispose(asmname);
+       end;*)
+end;
+
+
+function Tabsolutesym.mangledname : string;
+
+begin
+    case abstyp of
+        tovar :
+            mangledname:=ref^.mangledname;
+        toasm :
+            mangledname:=asmname^;
+        toaddr :
+            mangledname:='$'+tostr(address);
+        else
+            internalerror(10002);
+    end;
+end;
+
+{****************************************************************************
+                                  Tfuncretsym
+****************************************************************************}
+
+constructor Tfuncretsym.init(const n:string;approcinfo:pointer{pprocinfo});
+
+begin
+    inherited init(n);
+    funcretprocinfo:=approcinfo;
+{   funcretdef:=Pprocinfo(approcinfo)^.retdef;}
+    { address valid for ret in param only }
+    { otherwise set by insert             }
+{   address:=pprocinfo(approcinfo)^.retoffset;}
+end;
+
+constructor Tfuncretsym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+{   funcretdef:=readdefref;
+    address:=readlong;
+    funcretprocinfo:=nil;
+    typ:=funcretsym;}
+end;
+
+procedure Tfuncretsym.store(var s:Tstream);
+
+begin
+     (*
+      Normally all references are
+      transfered to the function symbol itself !! PM *)
+    inherited store(s);
+{   writedefref(funcretdef);
+    writelong(address);
+
+    current_ppu^.writeentry(ibfuncretsym);}
+end;
+
+procedure Tfuncretsym.deref;
+
+begin
+    {resolvedef(funcretdef);}
+end;
+
+procedure Tfuncretsym.insert_in_data;
+
+var l:longint;
+
+begin
+    {Allocate space in local if ret in acc or in fpu.}
+{   if dp_ret_in_acc in procinfo.retdef^.properties
+     or (procinfo.retdef^.deftype=floatdef) then
+        begin
+            l:=funcretdef^.size;
+            adress:=owner^.varsymtodata('',l);
+            procinfo.retoffset:=-owner^.datasize;
+        end;}
+end;
+
+constructor tpropertysym.load(var s:Tstream);
+
+begin
+    inherited load(s);
+(*  proptype:=readdefref;
+    options:=readlong;
+    index:=readlong;
+    default:=readlong;
+    { it's hack ... }
+    readaccesssym:=psym(stringdup(readstring));
+    writeaccesssym:=psym(stringdup(readstring));
+    storedsym:=psym(stringdup(readstring));
+    { now the defs: }
+    readaccessdef:=readdefref;
+    writeaccessdef:=readdefref;
+    storeddef:=readdefref;*)
+end;
+
+procedure Tpropertysym.deref;
+
+begin
+(*  resolvedef(proptype);
+    resolvedef(readaccessdef);
+    resolvedef(writeaccessdef);
+    resolvedef(storeddef);
+    { solve the hack we did in load: }
+    if pstring(readaccesssym)^<>'' then
+      begin
+         srsym:=search_class_member(pobjectdef(owner^.defowner),pstring(readaccesssym)^);
+         if not(assigned(srsym)) then
+           srsym:=generrorsym;
+      end
+    else
+      srsym:=nil;
+    stringdispose(pstring(readaccesssym));
+    readaccesssym:=srsym;
+
+    if pstring(writeaccesssym)^<>'' then
+      begin
+         srsym:=search_class_member(pobjectdef(owner^.defowner),pstring(writeaccesssym)^);
+         if not(assigned(srsym)) then
+           srsym:=generrorsym;
+      end
+    else
+      srsym:=nil;
+    stringdispose(pstring(writeaccesssym));
+    writeaccesssym:=srsym;
+
+    if pstring(storedsym)^<>'' then
+      begin
+         srsym:=search_class_member(pobjectdef(owner^.defowner),pstring(storedsym)^);
+         if not(assigned(srsym)) then
+           srsym:=generrorsym;
+      end
+    else
+      srsym:=nil;
+    stringdispose(pstring(storedsym));
+    storedsym:=srsym;*)
+end;
+
+function Tpropertysym.getsize:longint;
+
+begin
+    getsize:=0;
+end;
+
+procedure Tpropertysym.store(var s:Tstream);
+
+begin
+    Tsym.store(s);
+(*  writedefref(proptype);
+    writelong(options);
+    writelong(index);
+    writelong(default);
+    if assigned(readaccesssym) then
+        writestring(readaccesssym^.name)
+    else
+        writestring('');
+    if assigned(writeaccesssym) then
+      writestring(writeaccesssym^.name)
+    else
+      writestring('');
+    if assigned(storedsym) then
+      writestring(storedsym^.name)
+    else
+      writestring('');
+    writedefref(readaccessdef);
+    writedefref(writeaccessdef);
+    writedefref(storeddef);
+    current_ppu^.writeentry(ibpropertysym);*)
+end;
+
+end.

+ 555 - 0
compiler/new/symtable/symtable.pas

@@ -0,0 +1,555 @@
+{
+    $Id$
+    Copyright (c) 1993-98 by Florian Klaempfl, Pierre Muller
+
+    This unit handles the 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 symtable;
+
+interface
+
+uses    objects,cobjects,aasm,globtype,i386base;
+
+
+type    Tdefprop=(dp_regable,           {Can be stored into a register.}
+                  dp_pointer_param,     {A pointer should be used
+                                         instead of the value for
+                                         parameters of this definition.}
+                  dp_ret_in_acc);       {Function results of this
+                                         definition can be returned into
+                                         the accumulator.}
+
+        Tdefpropset=set of Tdefprop;
+        Psymtable=^Tsymtable;
+        Pcontainingsymtable=^Tcontainingsymtable;
+        Pref=^Tref;
+        Psymtableentry=^Tsymtableentry;
+        Psym=^Tsym;
+        Pdef=^Tdef;
+
+        Tsymtable=object(Tobject)
+            name:Pstring;
+            datasize:longint;
+            procedure foreach(proc2call:Tnamedindexcallback);virtual;
+            procedure insert(sym:Psym);virtual;
+            function search(const s:stringid):Psym;
+            function speedsearch(const s:stringid;
+                                 speedvalue:longint):Psym;virtual;
+            function tconstsymtodata(sym:Psym;len:longint):longint;virtual;
+            function varsymprefix:string;virtual;
+            function varsymtodata(sym:Psym;len:longint):longint;virtual;
+        end;
+
+        Tcontainingsymtable=object(Tsymtable)
+            alignment:byte;         {Aligment used in this symtable.}
+            index_growsize:word;    {The delta of the defindex collection.}
+            defindex:Pcollection;   {Contains all definitions in symtable.}
+            symsearch:Pdictionary;
+            constructor init;
+            constructor load(var s:Tstream);
+            procedure set_contents(s:Pdictionary;d:Pcollection);
+            {Get_contents disposes the symtable object!!}
+            procedure get_contents(var s:Pdictionary;var d:Pcollection);
+            {Checks if all variabeles are used.}
+            procedure check_vars;
+            {Checks if all forwards resolved.}
+            procedure check_forwards;
+            {Checks if all labels used.}
+            procedure check_labels;
+            procedure foreach(proc2call:Tnamedindexcallback);virtual;
+            procedure insert(sym:Psym);virtual;
+            function speedsearch(const s:stringid;
+                                 speedvalue:longint):Psym;virtual;
+            procedure store(var s:Tstream);virtual;
+            procedure registerdef(p:Pdef);
+            destructor done;virtual;
+        end;
+
+        Tref=object(Tobject)
+            posinfo:Tfileposinfo;
+            moduleindex:word;
+            constructor init(const pos:Tfileposinfo);
+            destructor done;virtual;
+        end;
+
+        Tsymtableentry=object(Tnamedindexobject)
+            owner:Pcontainingsymtable;
+        end;
+
+        Tsymprop=byte;
+
+        Tsym=object(Tsymtableentry)
+            fileinfo:Tfileposinfo;
+            references:Pcollection;     {Contains all references to symbol.}
+            constructor init(const n : string);
+            constructor load(var s:Tstream);
+            procedure deref;virtual;
+            procedure make_reference;
+            function mangledname:string;virtual;
+            procedure insert_in_data;virtual;
+            procedure load_references;virtual;
+            procedure register_defs;virtual;
+            procedure store(var s:Tstream);virtual;
+            function write_references:boolean;virtual;
+{$ifdef BrowserLog}
+            procedure add_to_browserlog;virtual;
+{$endif BrowserLog}
+            destructor done;virtual;
+        end;
+
+        Tdef=object(Tobject)
+            savesize:longint;
+            sym:Psym;
+            owner:Pcontainingsymtable;
+            properties:Tdefpropset;
+            inittable:Pasmlabel;        {Nil, or pointer to inittable.}
+            rtti:Pasmlabel;             {Nil, or pointer to rtti.}
+            constructor init(Aowner:Pcontainingsymtable);
+            constructor load(var s:Tstream);
+            destructor done;virtual;
+            {procedure correct_owner_symtable; REMOVED
+             enumdefs can be safely in a record or object symtable,
+             but the enum symbols must be in owners symtable.}
+            procedure store(var s:Tstream);virtual;
+            {Returns the typename of this definition.}
+            function typename:string;virtual;
+            procedure deref;virtual;
+            function size:longint;virtual;
+            procedure symderef;virtual;
+            {Init. tables }
+            function  needs_inittable:boolean;virtual;
+            procedure generate_inittable;
+            function get_inittable_label:Pasmlabel;
+            {The default implemenation calls write_rtti_data
+             if init and rtti data is different these procedures
+             must be overloaded.}
+            procedure write_init_data;virtual;
+            {Writes rtti of child to avoid mixup of rtti.}
+            procedure write_child_init_data;virtual;
+
+            {Rtti}
+            procedure write_rtti_name;
+            function  get_rtti_label:string;virtual;
+            procedure generate_rtti;virtual;
+            procedure write_rtti_data;virtual;
+            procedure write_child_rtti_data;virtual;
+
+            { returns true, if the definition can be published }
+            function is_publishable : boolean;virtual;
+            function gettypename:string;virtual;
+        end;
+
+const   systemunit:Psymtable            = nil; {Pointer to the system unit.}
+        objpasunit:Psymtable            = nil; {Pointer to the objpas unit.}
+
+var     read_member : boolean;      {True, wenn Members aus einer PPU-
+                                     Datei gelesen werden, d.h. ein
+                                     varsym seine Adresse einlesen soll }
+        procprefix:stringid;
+
+{**************************************************************************}
+
+implementation
+
+{**************************************************************************}
+
+uses    symtablt,files,verbose,globals;
+
+
+{****************************************************************************
+                                Tsymtable
+****************************************************************************}
+
+
+procedure Tsymtable.foreach(proc2call:Tnamedindexcallback);
+
+begin
+    abstract;
+end;
+
+procedure Tsymtable.insert(sym:Psym);
+
+begin
+    abstract;
+end;
+
+function Tsymtable.search(const s:stringid):Psym;
+
+begin
+    search:=speedsearch(s,getspeedvalue(s));
+end;
+
+function Tsymtable.speedsearch(const s:stringid;speedvalue:longint):Psym;
+
+begin
+    abstract;
+end;
+
+function Tsymtable.tconstsymtodata(sym:Psym;len:longint):longint;
+
+begin
+    tconstsymtodata:=datasize;
+    inc(datasize,len);
+end;
+
+function Tsymtable.varsymprefix:string;
+
+begin
+    abstract;
+end;
+
+function Tsymtable.varsymtodata(sym:Psym;len:longint):longint;
+
+begin
+    varsymtodata:=datasize;
+    inc(datasize,len);
+end;
+
+{****************************************************************************
+                            Tcontainingsymtable
+****************************************************************************}
+
+constructor Tcontainingsymtable.init;
+
+var indexgrow:word;
+
+begin
+    indexgrow:=index_growsize;
+    new(defindex,init(2*indexgrow,indexgrow));
+    new(symsearch,init);
+    alignment:=def_alignment;
+    index_growsize:=16;
+end;
+
+constructor Tcontainingsymtable.load;
+
+begin
+end;
+
+procedure Tcontainingsymtable.get_contents(var s:Pdictionary;
+                                           var d:Pcollection);
+
+begin
+    s:=symsearch;
+    d:=defindex;
+    free;
+end;
+
+procedure Tcontainingsymtable.store(var s:Tstream);
+
+begin
+end;
+
+procedure Tcontainingsymtable.check_vars;
+
+begin
+end;
+
+procedure Tcontainingsymtable.check_forwards;
+
+begin
+end;
+
+procedure Tcontainingsymtable.check_labels;
+
+begin
+end;
+
+procedure Tcontainingsymtable.foreach(proc2call:Tnamedindexcallback);
+
+begin
+    symsearch^.foreach(proc2call);
+end;
+
+procedure Tcontainingsymtable.insert(sym:Psym);
+
+begin
+    symsearch^.insert(sym);
+    sym^.register_defs;
+end;
+
+procedure Tcontainingsymtable.set_contents(s:Pdictionary;d:Pcollection);
+
+begin
+    dispose(defindex,done);
+    dispose(symsearch,done);
+    defindex:=d;
+    symsearch:=s;
+end;
+
+function Tcontainingsymtable.speedsearch(const s:stringid;
+                                         speedvalue:longint):Psym;
+
+var r:Psym;
+
+begin
+    r:=Psym(symsearch^.speedsearch(s,speedvalue));
+    {Make a notice that the symbol is referenced.}
+    if (r<>nil) and (cs_browser in aktmoduleswitches) and make_ref then
+        r^.make_reference;
+    speedsearch:=r;
+end;
+
+procedure Tcontainingsymtable.registerdef(p:Pdef);
+
+begin
+    defindex^.insert(p);
+    p^.owner:=@self;
+end;
+
+destructor Tcontainingsymtable.done;
+
+begin
+    dispose(defindex,done);
+    dispose(symsearch,done);
+    inherited done;
+end;
+
+{****************************************************************************
+                                    Tref
+****************************************************************************}
+
+constructor Tref.init(const pos:Tfileposinfo);
+
+begin
+    inherited init;
+    posinfo:=pos;
+    moduleindex:=current_module^.unit_index;
+end;
+
+destructor Tref.done;
+
+var inputfile:Pinputfile;
+
+begin
+    inputfile:=get_source_file(moduleindex,posinfo.fileindex);
+    if inputfile<>nil then
+        dec(inputfile^.ref_count);
+end;
+
+procedure duplicatesym(sym:Psym);
+
+begin
+    message1(sym_e_duplicate_id,sym^.name);
+    with sym^.fileinfo do
+        message2(sym_h_duplicate_id_where,
+         current_module^.sourcefiles^.get_file_name(fileindex),tostr(line));
+end;
+
+{****************************************************************************
+                                    Tsym
+****************************************************************************}
+
+constructor Tsym.init(const n:string);
+
+begin
+    inherited init(n);
+    fileinfo:=tokenpos;
+    if cs_browser in aktmoduleswitches then
+        new(references,init(32,16));
+    {The place where a symbol is defined is also a reference. You can safely
+     assume that the first reference in the references collection is the
+     place where the symbol is defined.}
+    make_reference;
+end;
+
+constructor Tsym.load(var s:Tstream);
+
+begin
+end;
+
+procedure Tsym.deref;
+
+begin
+    abstract;
+end;
+
+procedure Tsym.insert_in_data;
+
+begin
+end;
+
+procedure Tsym.make_reference;
+
+begin
+    if (cs_browser in aktmoduleswitches) and make_ref then
+        references^.insert(new(Pref,init(tokenpos)));
+end;
+
+function Tsym.mangledname:string;
+
+begin
+    mangledname:=name;
+end;
+
+procedure Tsym.register_defs;
+
+begin
+end;
+
+procedure Tsym.store(var s:Tstream);
+
+begin
+end;
+
+destructor Tsym.done;
+
+begin
+    if references<>nil then
+        dispose(references,done);
+    inherited done;
+end;
+procedure Tsym.load_references;
+
+begin
+end;
+
+function Tsym.write_references:boolean;
+
+begin
+end;
+
+{****************************************************************************
+                                    Tdef
+****************************************************************************}
+
+constructor Tdef.init(Aowner:Pcontainingsymtable);
+
+begin
+    inherited init;
+    Aowner^.registerdef(@self);
+    owner:=Aowner;
+end;
+
+constructor Tdef.load;
+
+begin
+end;
+
+procedure Tdef.store(var s:Tstream);
+
+begin
+end;
+
+function Tdef.typename:string;
+
+begin
+    typename:='<unknown type>';
+end;
+
+procedure Tdef.deref;
+
+begin
+end;
+
+function Tdef.size:longint;
+
+begin
+    size:=savesize;
+end;
+
+procedure Tdef.symderef;
+
+begin
+end;
+
+function Tdef.needs_inittable:boolean;
+
+begin
+end;
+
+procedure Tdef.generate_inittable;
+
+begin
+end;
+
+function Tdef.get_inittable_label:Pasmlabel;
+
+begin
+end;
+
+procedure Tdef.write_init_data;
+
+begin
+end;
+
+procedure Tdef.write_child_init_data;
+
+begin
+end;
+
+procedure Tdef.write_rtti_name;
+
+begin
+end;
+
+function  Tdef.get_rtti_label:string;
+
+begin
+end;
+
+procedure Tdef.generate_rtti;
+
+begin
+end;
+
+procedure Tdef.write_rtti_data;
+
+begin
+end;
+
+procedure Tdef.write_child_rtti_data;
+
+begin
+end;
+
+
+function Tdef.is_publishable:boolean;
+
+begin
+    is_publishable:=false;
+end;
+
+
+function Tdef.gettypename:string;
+
+begin
+    gettypename:='<unknown type>';
+end;
+
+destructor Tdef.done;
+
+{var    s:Ptypesym;}
+
+begin
+{   s:=sym;
+    while s<>nil do
+        begin
+            s^.definition:=nil;
+            s:=s^.synonym;
+        end;}
+    inherited done;
+end;
+
+end.

+ 387 - 0
compiler/new/symtable/symtablt.pas

@@ -0,0 +1,387 @@
+{
+    $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(Tcontainingsymtable)
+            unitid:word;
+            function varsymprefix:string;virtual;
+        end;
+
+        Timplsymtable=object(Tcontainingsymtable)
+            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(Tcontainingsymtable)
+        end;
+
+        Tobjectsymtable=object(Tcontainingsymtable)
+            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.