mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-26 18:43:42 +02:00

(to have a easier way to test OS_SOURCE abd OS_TARGET in makefiles) * several problems with rtti data (type of sym was not checked) assumed to be varsym when they could be procsym or property syms !!
3473 lines
97 KiB
PHP
3473 lines
97 KiB
PHP
{
|
|
$Id$
|
|
Copyright (c) 1993-98 by Florian Klaempfl, Pierre Muller
|
|
|
|
Symbol table implementation for the definitions
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
****************************************************************************
|
|
}
|
|
|
|
{****************************************************************************
|
|
TDEF (base class for definitions)
|
|
****************************************************************************}
|
|
|
|
const
|
|
{ if you change one of the following contants, }
|
|
{ you have also to change the typinfo unit }
|
|
tkUnknown = 0;
|
|
tkInteger = 1;
|
|
tkChar = 2;
|
|
tkEnumeration = 3;
|
|
tkFloat = 4;
|
|
tkSet = 6;
|
|
tkMethod = 7;
|
|
tkSString = 8;
|
|
tkString = tkSString;
|
|
tkLString = 9;
|
|
tkAString = 10;
|
|
tkWString = 11;
|
|
tkVariant = 12;
|
|
tkArray = 13;
|
|
tkRecord = 14;
|
|
tkInterface = 15;
|
|
tkClass = 16;
|
|
tkObject = 17;
|
|
tkWChar = 18;
|
|
tkBool = 19;
|
|
|
|
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;
|
|
|
|
|
|
constructor tdef.init;
|
|
begin
|
|
deftype:=abstractdef;
|
|
owner := nil;
|
|
next := nil;
|
|
sym := nil;
|
|
indexnb := 0;
|
|
if registerdef then
|
|
symtablestack^.registerdef(@self);
|
|
has_rtti:=false;
|
|
has_inittable:=false;
|
|
{$ifdef GDB}
|
|
is_def_stab_written := false;
|
|
globalnb := 0;
|
|
{$endif GDB}
|
|
if assigned(lastglobaldef) then
|
|
begin
|
|
lastglobaldef^.nextglobal := @self;
|
|
previousglobal:=lastglobaldef;
|
|
end
|
|
else
|
|
begin
|
|
firstglobaldef := @self;
|
|
previousglobal := nil;
|
|
end;
|
|
lastglobaldef := @self;
|
|
nextglobal := nil;
|
|
end;
|
|
|
|
|
|
constructor tdef.load;
|
|
begin
|
|
deftype:=abstractdef;
|
|
indexnb := 0;
|
|
sym := nil;
|
|
owner := nil;
|
|
next := nil;
|
|
has_rtti:=false;
|
|
has_inittable:=false;
|
|
{$ifdef GDB}
|
|
is_def_stab_written := false;
|
|
globalnb := 0;
|
|
{$endif GDB}
|
|
if assigned(lastglobaldef) then
|
|
begin
|
|
lastglobaldef^.nextglobal := @self;
|
|
previousglobal:=lastglobaldef;
|
|
end
|
|
else
|
|
begin
|
|
firstglobaldef := @self;
|
|
previousglobal:=nil;
|
|
end;
|
|
lastglobaldef := @self;
|
|
nextglobal := nil;
|
|
end;
|
|
|
|
|
|
destructor tdef.done;
|
|
begin
|
|
{ first element ? }
|
|
if not(assigned(previousglobal)) then
|
|
begin
|
|
firstglobaldef := nextglobal;
|
|
if assigned(firstglobaldef) then
|
|
firstglobaldef^.previousglobal:=nil;
|
|
end
|
|
else
|
|
begin
|
|
{ remove reference in the element before }
|
|
previousglobal^.nextglobal:=nextglobal;
|
|
end;
|
|
{ last element ? }
|
|
if not(assigned(nextglobal)) then
|
|
begin
|
|
lastglobaldef := previousglobal;
|
|
if assigned(lastglobaldef) then
|
|
lastglobaldef^.nextglobal:=nil;
|
|
end
|
|
else
|
|
nextglobal^.previousglobal:=previousglobal;
|
|
previousglobal:=nil;
|
|
nextglobal:=nil;
|
|
end;
|
|
|
|
{ used for enumdef because the symbols are
|
|
inserted in the owner symtable }
|
|
procedure tdef.correct_owner_symtable;
|
|
var
|
|
st : psymtable;
|
|
begin
|
|
if assigned(owner) and
|
|
(owner^.symtabletype in [recordsymtable,objectsymtable]) then
|
|
begin
|
|
{ no other definition
|
|
has been inserted !! (PM) }
|
|
owner^.rootdef:=next;
|
|
st:=owner;
|
|
while (st^.symtabletype in [recordsymtable,objectsymtable]) do
|
|
st:=st^.next;
|
|
st^.registerdef(@self);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tdef.write;
|
|
begin
|
|
{$ifdef GDB}
|
|
if globalnb = 0 then
|
|
begin
|
|
if assigned(owner) then
|
|
globalnb := owner^.getnewtypecount
|
|
else
|
|
begin
|
|
globalnb := PGlobalTypeCount^;
|
|
Inc(PGlobalTypeCount^);
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
end;
|
|
|
|
|
|
function tdef.size : longint;
|
|
begin
|
|
size:=savesize;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
procedure tdef.set_globalnb;
|
|
begin
|
|
globalnb :=PGlobalTypeCount^;
|
|
inc(PglobalTypeCount^);
|
|
end;
|
|
|
|
|
|
function tdef.stabstring : pchar;
|
|
begin
|
|
stabstring := strpnew('t'+numberstring+';');
|
|
end;
|
|
|
|
|
|
function tdef.numberstring : string;
|
|
var table : psymtable;
|
|
begin
|
|
{formal def have no type !}
|
|
if deftype = formaldef then
|
|
begin
|
|
numberstring := voiddef^.numberstring;
|
|
exit;
|
|
end;
|
|
if (not assigned(sym)) or (not sym^.isusedinstab) then
|
|
begin
|
|
{set even if debuglist is not defined}
|
|
if assigned(sym) then
|
|
sym^.isusedinstab := true;
|
|
if assigned(debuglist) and not is_def_stab_written then
|
|
concatstabto(debuglist);
|
|
end;
|
|
if not use_dbx then
|
|
begin
|
|
if globalnb = 0 then
|
|
set_globalnb;
|
|
numberstring := tostr(globalnb);
|
|
end
|
|
else
|
|
begin
|
|
if globalnb = 0 then
|
|
begin
|
|
if assigned(owner) then
|
|
globalnb := owner^.getnewtypecount
|
|
else
|
|
begin
|
|
globalnb := PGlobalTypeCount^;
|
|
Inc(PGlobalTypeCount^);
|
|
end;
|
|
end;
|
|
if assigned(sym) then
|
|
begin
|
|
table := sym^.owner;
|
|
if table^.unitid > 0 then
|
|
numberstring := '('+tostr(table^.unitid)+','
|
|
+tostr(sym^.definition^.globalnb)+')'
|
|
else
|
|
numberstring := tostr(globalnb);
|
|
exit;
|
|
end;
|
|
numberstring := tostr(globalnb);
|
|
end;
|
|
end;
|
|
|
|
|
|
function tdef.allstabstring : pchar;
|
|
var stabchar : string[2];
|
|
ss,st : pchar;
|
|
name : string;
|
|
sym_line_no : longint;
|
|
begin
|
|
ss := stabstring;
|
|
getmem(st,strlen(ss)+512);
|
|
stabchar := 't';
|
|
if deftype in tagtypes then
|
|
stabchar := 'Tt';
|
|
if assigned(sym) then
|
|
begin
|
|
name := sym^.name;
|
|
sym_line_no:=sym^.fileinfo.line;
|
|
end
|
|
else
|
|
begin
|
|
name := ' ';
|
|
sym_line_no:=0;
|
|
end;
|
|
strpcopy(st,'"'+name+':'+stabchar+numberstring+'=');
|
|
strpcopy(strecopy(strend(st),ss),'",'+tostr(N_LSYM)+',0,'+tostr(sym_line_no)+',0');
|
|
allstabstring := strnew(st);
|
|
freemem(st,strlen(ss)+512);
|
|
strdispose(ss);
|
|
end;
|
|
|
|
|
|
procedure tdef.concatstabto(asmlist : paasmoutput);
|
|
var stab_str : pchar;
|
|
begin
|
|
if ((sym = nil) or sym^.isusedinstab or use_dbx)
|
|
and not is_def_stab_written then
|
|
begin
|
|
If use_dbx then
|
|
begin
|
|
{ otherwise you get two of each def }
|
|
If assigned(sym) then
|
|
begin
|
|
if sym^.typ=typesym then
|
|
sym^.isusedinstab:=true;
|
|
if (sym^.owner = nil) or
|
|
((sym^.owner^.symtabletype = unitsymtable) and
|
|
punitsymtable(sym^.owner)^.dbx_count_ok) then
|
|
begin
|
|
{with DBX we get the definition from the other objects }
|
|
is_def_stab_written := true;
|
|
exit;
|
|
end;
|
|
end;
|
|
end;
|
|
{ to avoid infinite loops }
|
|
is_def_stab_written := true;
|
|
stab_str := allstabstring;
|
|
if asmlist = debuglist then do_count_dbx := true;
|
|
{ count_dbx(stab_str); moved to GDB.PAS}
|
|
asmlist^.concat(new(pai_stabs,init(stab_str)));
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
procedure tdef.deref;
|
|
begin
|
|
end;
|
|
|
|
|
|
{ rtti generation }
|
|
procedure tdef.generate_rtti;
|
|
begin
|
|
has_rtti:=true;
|
|
getlabel(rtti_label);
|
|
write_child_rtti_data;
|
|
rttilist^.concat(new(pai_label,init(rtti_label)));
|
|
write_rtti_data;
|
|
end;
|
|
|
|
|
|
function tdef.get_rtti_label : plabel;
|
|
begin
|
|
if not(has_rtti) then
|
|
generate_rtti;
|
|
get_rtti_label:=rtti_label;
|
|
end;
|
|
|
|
|
|
{ init table handling }
|
|
function tdef.needs_inittable : boolean;
|
|
begin
|
|
needs_inittable:=false;
|
|
end;
|
|
|
|
|
|
procedure tdef.generate_inittable;
|
|
begin
|
|
has_inittable:=true;
|
|
getlabel(inittable_label);
|
|
write_child_init_data;
|
|
rttilist^.concat(new(pai_label,init(inittable_label)));
|
|
write_init_data;
|
|
end;
|
|
|
|
|
|
procedure tdef.write_init_data;
|
|
begin
|
|
write_rtti_data;
|
|
end;
|
|
|
|
|
|
procedure tdef.write_child_init_data;
|
|
begin
|
|
write_child_rtti_data;
|
|
end;
|
|
|
|
|
|
function tdef.get_inittable_label : plabel;
|
|
begin
|
|
if not(has_inittable) then
|
|
generate_inittable;
|
|
get_inittable_label:=inittable_label;
|
|
end;
|
|
|
|
|
|
procedure tdef.writename;
|
|
var
|
|
str : string;
|
|
begin
|
|
{ name }
|
|
if assigned(sym) then
|
|
begin
|
|
str:=sym^.name;
|
|
rttilist^.concat(new(pai_string,init(chr(length(str))+str)));
|
|
end
|
|
else
|
|
rttilist^.concat(new(pai_string,init(#0)))
|
|
end;
|
|
|
|
|
|
{ returns true, if the definition can be published }
|
|
function tdef.is_publishable : boolean;
|
|
begin
|
|
is_publishable:=false;
|
|
end;
|
|
|
|
|
|
procedure tdef.write_rtti_data;
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure tdef.write_child_rtti_data;
|
|
begin
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
TSTRINGDEF
|
|
****************************************************************************}
|
|
|
|
constructor tstringdef.init(l : byte);
|
|
begin
|
|
tdef.init;
|
|
string_typ:=st_shortstring;
|
|
deftype:=stringdef;
|
|
len:=l;
|
|
savesize:=len+1;
|
|
end;
|
|
|
|
|
|
constructor tstringdef.load;
|
|
begin
|
|
tdef.load;
|
|
string_typ:=st_shortstring;
|
|
deftype:=stringdef;
|
|
len:=readbyte;
|
|
savesize:=len+1;
|
|
end;
|
|
|
|
|
|
constructor tstringdef.longinit(l : longint);
|
|
begin
|
|
tdef.init;
|
|
string_typ:=st_longstring;
|
|
deftype:=stringdef;
|
|
len:=l;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tstringdef.longload;
|
|
begin
|
|
tdef.load;
|
|
deftype:=stringdef;
|
|
string_typ:=st_longstring;
|
|
len:=readlong;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tstringdef.ansiinit(l : longint);
|
|
begin
|
|
tdef.init;
|
|
string_typ:=st_ansistring;
|
|
deftype:=stringdef;
|
|
len:=l;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tstringdef.ansiload;
|
|
begin
|
|
tdef.load;
|
|
deftype:=stringdef;
|
|
string_typ:=st_ansistring;
|
|
len:=readlong;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tstringdef.wideinit(l : longint);
|
|
begin
|
|
tdef.init;
|
|
string_typ:=st_widestring;
|
|
deftype:=stringdef;
|
|
len:=l;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tstringdef.wideload;
|
|
begin
|
|
tdef.load;
|
|
deftype:=stringdef;
|
|
string_typ:=st_widestring;
|
|
len:=readlong;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
function tstringdef.size : longint;
|
|
begin
|
|
size:=savesize;
|
|
end;
|
|
|
|
|
|
procedure tstringdef.write;
|
|
begin
|
|
tdef.write;
|
|
if string_typ=st_shortstring then
|
|
writebyte(len)
|
|
else
|
|
writelong(len);
|
|
case string_typ of
|
|
st_shortstring : current_ppu^.writeentry(ibstringdef);
|
|
st_longstring : current_ppu^.writeentry(iblongstringdef);
|
|
st_ansistring : current_ppu^.writeentry(ibansistringdef);
|
|
st_widestring : current_ppu^.writeentry(ibwidestringdef);
|
|
end;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tstringdef.stabstring : pchar;
|
|
var
|
|
bytest,charst,longst : string;
|
|
begin
|
|
case string_typ of
|
|
st_shortstring:
|
|
begin
|
|
charst := typeglobalnumber('char');
|
|
{ this is what I found in stabs.texinfo but
|
|
gdb 4.12 for go32 doesn't understand that !! }
|
|
{$IfDef GDBknowsstrings}
|
|
stabstring := strpnew('n'+charst+';'+tostr(len));
|
|
{$else}
|
|
bytest := typeglobalnumber('byte');
|
|
stabstring := strpnew('s'+tostr(len+1)+'length:'+bytest
|
|
+',0,8;st:ar'+bytest
|
|
+';1;'+tostr(len)+';'+charst+',8,'+tostr(len*8)+';;');
|
|
{$EndIf}
|
|
end;
|
|
st_longstring:
|
|
begin
|
|
charst := typeglobalnumber('char');
|
|
{ this is what I found in stabs.texinfo but
|
|
gdb 4.12 for go32 doesn't understand that !! }
|
|
{$IfDef GDBknowsstrings}
|
|
stabstring := strpnew('n'+charst+';'+tostr(len));
|
|
{$else}
|
|
bytest := typeglobalnumber('byte');
|
|
longst := typeglobalnumber('longint');
|
|
stabstring := strpnew('s'+tostr(len+5)+'length:'+longst
|
|
+',0,32;dummy:'+bytest+',32,8;st:ar'+bytest
|
|
+';1;'+tostr(len)+';'+charst+',40,'+tostr(len*8)+';;');
|
|
{$EndIf}
|
|
end;
|
|
st_ansistring:
|
|
begin
|
|
{ an ansi string looks like a pchar easy !! }
|
|
stabstring:=strpnew('*'+typeglobalnumber('char'));
|
|
end;
|
|
st_widestring:
|
|
begin
|
|
{ an ansi string looks like a pchar easy !! }
|
|
stabstring:=strpnew('*'+typeglobalnumber('char'));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tstringdef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
function tstringdef.needs_inittable : boolean;
|
|
begin
|
|
needs_inittable:=string_typ in [st_ansistring,st_widestring];
|
|
end;
|
|
|
|
|
|
procedure tstringdef.write_rtti_data;
|
|
begin
|
|
case string_typ of
|
|
st_ansistring:
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(tkAString)));
|
|
end;
|
|
st_widestring:
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(tkWString)));
|
|
end;
|
|
st_longstring:
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(tkLString)));
|
|
end;
|
|
st_shortstring:
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(tkSString)));
|
|
rttilist^.concat(new(pai_const,init_8bit(len)));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function tstringdef.is_publishable : boolean;
|
|
begin
|
|
is_publishable:=true;
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
TENUMDEF
|
|
****************************************************************************}
|
|
|
|
constructor tenumdef.init;
|
|
begin
|
|
tdef.init;
|
|
deftype:=enumdef;
|
|
minval:=0;
|
|
maxval:=0;
|
|
calcsavesize;
|
|
has_jumps:=false;
|
|
basedef:=nil;
|
|
rangenr:=0;
|
|
first:=nil;
|
|
correct_owner_symtable;
|
|
end;
|
|
|
|
constructor tenumdef.init_subrange(_basedef:penumdef;_min,_max:longint);
|
|
begin
|
|
tdef.init;
|
|
deftype:=enumdef;
|
|
minval:=_min;
|
|
maxval:=_max;
|
|
basedef:=_basedef;
|
|
calcsavesize;
|
|
has_jumps:=false;
|
|
rangenr:=0;
|
|
first:=nil;
|
|
correct_owner_symtable;
|
|
end;
|
|
|
|
|
|
constructor tenumdef.load;
|
|
begin
|
|
tdef.load;
|
|
deftype:=enumdef;
|
|
basedef:=penumdef(readdefref);
|
|
minval:=readlong;
|
|
maxval:=readlong;
|
|
savesize:=readlong;
|
|
has_jumps:=false;
|
|
first:=Nil;
|
|
end;
|
|
|
|
|
|
procedure tenumdef.calcsavesize;
|
|
begin
|
|
if (aktpackenum=4) or (min<0) or (max>65535) then
|
|
savesize:=4
|
|
else
|
|
if (aktpackenum=2) or (min<0) or (max>255) then
|
|
savesize:=2
|
|
else
|
|
savesize:=1;
|
|
end;
|
|
|
|
|
|
procedure tenumdef.setmax(_max:longint);
|
|
begin
|
|
maxval:=_max;
|
|
calcsavesize;
|
|
end;
|
|
|
|
|
|
procedure tenumdef.setmin(_min:longint);
|
|
begin
|
|
minval:=_min;
|
|
calcsavesize;
|
|
end;
|
|
|
|
|
|
function tenumdef.min:longint;
|
|
begin
|
|
min:=minval;
|
|
end;
|
|
|
|
|
|
function tenumdef.max:longint;
|
|
begin
|
|
max:=maxval;
|
|
end;
|
|
|
|
|
|
procedure tenumdef.deref;
|
|
begin
|
|
resolvedef(pdef(basedef));
|
|
end;
|
|
|
|
|
|
destructor tenumdef.done;
|
|
begin
|
|
inherited done;
|
|
end;
|
|
|
|
|
|
procedure tenumdef.write;
|
|
begin
|
|
tdef.write;
|
|
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,init_global(getrangecheckstring)))
|
|
else
|
|
datasegment^.concat(new(pai_symbol,init(getrangecheckstring)));
|
|
datasegment^.concat(new(pai_const,init_32bit(min)));
|
|
datasegment^.concat(new(pai_const,init_32bit(max)));
|
|
end;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tenumdef.stabstring : pchar;
|
|
var st,st2 : pchar;
|
|
p : penumsym;
|
|
s : string;
|
|
memsize : word;
|
|
begin
|
|
memsize := memsizeinc;
|
|
getmem(st,memsize);
|
|
strpcopy(st,'e');
|
|
p := first;
|
|
while assigned(p) do
|
|
begin
|
|
s :=p^.name+':'+tostr(p^.value)+',';
|
|
{ place for the ending ';' also }
|
|
if (strlen(st)+length(s)+1<memsize) then
|
|
strpcopy(strend(st),s)
|
|
else
|
|
begin
|
|
getmem(st2,memsize+memsizeinc);
|
|
strcopy(st2,st);
|
|
freemem(st,memsize);
|
|
st := st2;
|
|
memsize := memsize+memsizeinc;
|
|
strpcopy(strend(st),s);
|
|
end;
|
|
p := p^.next;
|
|
end;
|
|
strpcopy(strend(st),';');
|
|
stabstring := strnew(st);
|
|
freemem(st,memsize);
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
procedure tenumdef.write_child_rtti_data;
|
|
begin
|
|
if assigned(basedef) then
|
|
basedef^.get_rtti_label;
|
|
end;
|
|
|
|
|
|
procedure tenumdef.write_rtti_data;
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(tkEnumeration)));
|
|
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(min)));
|
|
rttilist^.concat(new(pai_const,init_32bit(max)));
|
|
if assigned(basedef) then
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(lab2str(basedef^.get_rtti_label)))))
|
|
else
|
|
rttilist^.concat(new(pai_const,init_32bit(0)));
|
|
{!!!!!!! Name list }
|
|
end;
|
|
|
|
|
|
function tenumdef.is_publishable : boolean;
|
|
begin
|
|
is_publishable:=true;
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
TORDDEF
|
|
****************************************************************************}
|
|
|
|
constructor torddef.init(t : tbasetype;v,b : longint);
|
|
begin
|
|
inherited init;
|
|
deftype:=orddef;
|
|
low:=v;
|
|
high:=b;
|
|
typ:=t;
|
|
rangenr:=0;
|
|
setsize;
|
|
end;
|
|
|
|
|
|
constructor torddef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=orddef;
|
|
typ:=tbasetype(readbyte);
|
|
low:=readlong;
|
|
high:=readlong;
|
|
rangenr:=0;
|
|
setsize;
|
|
end;
|
|
|
|
|
|
procedure torddef.setsize;
|
|
begin
|
|
if typ=uauto then
|
|
begin
|
|
{ generate a unsigned range if high<0 and low>=0 }
|
|
if (low>=0) and (high<0) then
|
|
begin
|
|
savesize:=4;
|
|
typ:=u32bit;
|
|
end
|
|
else if (low>=0) and (high<=255) then
|
|
begin
|
|
savesize:=1;
|
|
typ:=u8bit;
|
|
end
|
|
else if (low>=-128) and (high<=127) then
|
|
begin
|
|
savesize:=1;
|
|
typ:=s8bit;
|
|
end
|
|
else if (low>=0) and (high<=65536) then
|
|
begin
|
|
savesize:=2;
|
|
typ:=u16bit;
|
|
end
|
|
else if (low>=-32768) and (high<=32767) then
|
|
begin
|
|
savesize:=2;
|
|
typ:=s16bit;
|
|
end
|
|
else
|
|
begin
|
|
savesize:=4;
|
|
typ:=s32bit;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
case typ of
|
|
u8bit,s8bit,
|
|
uchar,bool8bit : savesize:=1;
|
|
u16bit,s16bit,
|
|
bool16bit : savesize:=2;
|
|
s32bit,u32bit,
|
|
bool32bit : savesize:=4;
|
|
else
|
|
savesize:=0;
|
|
end;
|
|
end;
|
|
{ there are no entrys for range checking }
|
|
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,init_global(getrangecheckstring)))
|
|
else
|
|
datasegment^.concat(new(pai_symbol,init(getrangecheckstring)));
|
|
if low<=high then
|
|
begin
|
|
datasegment^.concat(new(pai_const,init_32bit(low)));
|
|
datasegment^.concat(new(pai_const,init_32bit(high)));
|
|
end
|
|
{ for u32bit we need two bounds }
|
|
else
|
|
begin
|
|
datasegment^.concat(new(pai_const,init_32bit(low)));
|
|
datasegment^.concat(new(pai_const,init_32bit($7fffffff)));
|
|
inc(nextlabelnr);
|
|
if (cs_smartlink in aktmoduleswitches) then
|
|
datasegment^.concat(new(pai_symbol,init_global('R_'+current_module^.modulename^+tostr(rangenr+1))))
|
|
else
|
|
datasegment^.concat(new(pai_symbol,init('R_'+tostr(rangenr+1))));
|
|
datasegment^.concat(new(pai_const,init_32bit($80000000)));
|
|
datasegment^.concat(new(pai_const,init_32bit(high)));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure torddef.write;
|
|
begin
|
|
tdef.write;
|
|
writebyte(byte(typ));
|
|
writelong(low);
|
|
writelong(high);
|
|
current_ppu^.writeentry(iborddef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function torddef.stabstring : pchar;
|
|
begin
|
|
case typ of
|
|
uvoid : stabstring := strpnew(numberstring+';');
|
|
{GDB 4.12 for go32 doesn't like boolean as range for 0 to 1 !!!}
|
|
bool8bit,
|
|
bool16bit,
|
|
bool32bit : stabstring := strpnew('r'+numberstring+';0;255;');
|
|
{ u32bit : stabstring := strpnew('r'+
|
|
s32bitdef^.numberstring+';0;-1;'); }
|
|
else
|
|
stabstring := strpnew('r'+s32bitdef^.numberstring+';'+tostr(low)+';'+tostr(high)+';');
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
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;
|
|
rttilist^.concat(new(pai_const,init_8bit(byte(trans[typ]))));
|
|
rttilist^.concat(new(pai_const,init_32bit(low)));
|
|
rttilist^.concat(new(pai_const,init_32bit(high)));
|
|
end;
|
|
|
|
|
|
function torddef.is_publishable : boolean;
|
|
begin
|
|
is_publishable:=typ in [uchar..bool8bit];
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
TFLOATDEF
|
|
****************************************************************************}
|
|
|
|
constructor tfloatdef.init(t : tfloattype);
|
|
begin
|
|
inherited init;
|
|
deftype:=floatdef;
|
|
typ:=t;
|
|
setsize;
|
|
end;
|
|
|
|
|
|
constructor tfloatdef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=floatdef;
|
|
typ:=tfloattype(readbyte);
|
|
setsize;
|
|
end;
|
|
|
|
|
|
procedure tfloatdef.setsize;
|
|
begin
|
|
case typ of
|
|
f16bit : savesize:=2;
|
|
f32bit,
|
|
s32real : savesize:=4;
|
|
s64real : savesize:=8;
|
|
s64bit : savesize:=8;
|
|
s80real : savesize:=extended_size;
|
|
else
|
|
savesize:=0;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tfloatdef.write;
|
|
begin
|
|
inherited write;
|
|
writebyte(byte(typ));
|
|
current_ppu^.writeentry(ibfloatdef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tfloatdef.stabstring : pchar;
|
|
begin
|
|
case typ of
|
|
s32real,
|
|
s64real : stabstring := strpnew('r'+
|
|
s32bitdef^.numberstring+';'+tostr(savesize)+';0;');
|
|
{ for fixed real use longint instead to be able to }
|
|
{ debug something at least }
|
|
f32bit:
|
|
stabstring := s32bitdef^.stabstring;
|
|
f16bit:
|
|
stabstring := strpnew('r'+s32bitdef^.numberstring+';0;'+
|
|
tostr($ffff)+';');
|
|
{ found this solution in stabsread.c from GDB v4.16 }
|
|
s64bit : stabstring := strpnew('r'+
|
|
s32bitdef^.numberstring+';-'+tostr(savesize)+';0;');
|
|
{$ifdef i386}
|
|
{ under dos at least you must give a size of twelve instead of 10 !! }
|
|
{ this is probably do to the fact that in gcc all is pushed in 4 bytes size }
|
|
s80real : stabstring := strpnew('r'+s32bitdef^.numberstring+';12;0;');
|
|
{$endif i386}
|
|
else
|
|
internalerror(10005);
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
procedure tfloatdef.write_rtti_data;
|
|
const
|
|
translate : array[tfloattype] of byte =
|
|
(ftFixed32,ftSingle,ftDouble,ftExtended,ftComp,ftFixed16);
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(tkFloat)));
|
|
rttilist^.concat(new(pai_const,init_8bit(translate[typ])));
|
|
end;
|
|
|
|
|
|
function tfloatdef.is_publishable : boolean;
|
|
begin
|
|
is_publishable:=true;
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
TFILEDEF
|
|
****************************************************************************}
|
|
|
|
constructor tfiledef.init(ft : tfiletype;tas : pdef);
|
|
begin
|
|
inherited init;
|
|
deftype:=filedef;
|
|
filetype:=ft;
|
|
typed_as:=tas;
|
|
setsize;
|
|
end;
|
|
|
|
|
|
constructor tfiledef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=filedef;
|
|
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.write;
|
|
begin
|
|
inherited write;
|
|
writebyte(byte(filetype));
|
|
if filetype=ft_typed then
|
|
writedefref(typed_as);
|
|
current_ppu^.writeentry(ibfiledef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tfiledef.stabstring : pchar;
|
|
begin
|
|
{$IfDef GDBknowsfiles}
|
|
case filetyp of
|
|
ft_typed : stabstring := strpnew('d'+typed_as^.numberstring{+';'});
|
|
ft_untyped : stabstring := strpnew('d'+voiddef^.numberstring{+';'});
|
|
ft_text : stabstring := strpnew('d'+cchardef^.numberstring{+';'});
|
|
end;
|
|
{$Else}
|
|
{based on
|
|
FileRec = Packed Record
|
|
Handle,
|
|
Mode,
|
|
RecSize : longint;
|
|
_private : array[1..32] of byte;
|
|
UserData : array[1..16] of byte;
|
|
name : array[0..255] of char;
|
|
End; }
|
|
{ the buffer part is still missing !! (PM) }
|
|
{ but the string could become too long !! }
|
|
stabstring := strpnew('s'+tostr(savesize)+
|
|
'HANDLE:'+typeglobalnumber('longint')+',0,32;'+
|
|
'MODE:'+typeglobalnumber('longint')+',32,32;'+
|
|
'RECSIZE:'+typeglobalnumber('longint')+',64,32;'+
|
|
'_PRIVATE:ar'+typeglobalnumber('word')+';1;32;'+typeglobalnumber('byte')
|
|
+',96,256;'+
|
|
'USERDATA:ar'+typeglobalnumber('word')+';1;16;'+typeglobalnumber('byte')
|
|
+',352,128;'+
|
|
'NAME:ar'+typeglobalnumber('word')+';0;255;'+typeglobalnumber('char')
|
|
+',480,2048;;');
|
|
{$EndIf}
|
|
end;
|
|
|
|
|
|
procedure tfiledef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
{ most file defs are unnamed !!! }
|
|
if ((sym = nil) or sym^.isusedinstab or use_dbx) and not is_def_stab_written then
|
|
begin
|
|
if assigned(typed_as) then forcestabto(asmlist,typed_as);
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
TPOINTERDEF
|
|
****************************************************************************}
|
|
|
|
constructor tpointerdef.init(def : pdef);
|
|
begin
|
|
inherited init;
|
|
deftype:=pointerdef;
|
|
definition:=def;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tpointerdef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=pointerdef;
|
|
{ the real address in memory is calculated later (deref) }
|
|
definition:=readdefref;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
procedure tpointerdef.deref;
|
|
begin
|
|
resolvedef(definition);
|
|
end;
|
|
|
|
|
|
procedure tpointerdef.write;
|
|
begin
|
|
inherited write;
|
|
writedefref(definition);
|
|
current_ppu^.writeentry(ibpointerdef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tpointerdef.stabstring : pchar;
|
|
begin
|
|
stabstring := strpnew('*'+definition^.numberstring);
|
|
end;
|
|
|
|
|
|
procedure tpointerdef.concatstabto(asmlist : paasmoutput);
|
|
var st,nb : string;
|
|
sym_line_no : longint;
|
|
begin
|
|
if ( (sym=nil) or sym^.isusedinstab or use_dbx) and not is_def_stab_written then
|
|
begin
|
|
if assigned(definition) then
|
|
if definition^.deftype in [recorddef,objectdef] then
|
|
begin
|
|
is_def_stab_written := true;
|
|
{to avoid infinite recursion in record with next-like fields }
|
|
nb := definition^.numberstring;
|
|
is_def_stab_written := false;
|
|
if not definition^.is_def_stab_written then
|
|
begin
|
|
if assigned(definition^.sym) then
|
|
begin
|
|
if assigned(sym) then
|
|
begin
|
|
st := sym^.name;
|
|
sym_line_no:=sym^.fileinfo.line;
|
|
end
|
|
else
|
|
begin
|
|
st := ' ';
|
|
sym_line_no:=0;
|
|
end;
|
|
st := '"'+st+':t'+numberstring+'=*'+definition^.numberstring
|
|
+'=xs'+definition^.sym^.name+':",'+tostr(N_LSYM)+',0,'+tostr(sym_line_no)+',0';
|
|
if asmlist = debuglist then do_count_dbx := true;
|
|
asmlist^.concat(new(pai_stabs,init(strpnew(st))));
|
|
end;
|
|
end else inherited concatstabto(asmlist);
|
|
is_def_stab_written := true;
|
|
end else
|
|
begin
|
|
forcestabto(asmlist,definition);
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{****************************************************************************
|
|
TCLASSREFDEF
|
|
****************************************************************************}
|
|
|
|
constructor tclassrefdef.init(def : pdef);
|
|
begin
|
|
inherited init(def);
|
|
deftype:=classrefdef;
|
|
definition:=def;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tclassrefdef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=classrefdef;
|
|
end;
|
|
|
|
|
|
procedure tclassrefdef.write;
|
|
begin
|
|
{ be careful, tclassdefref inherits from tpointerdef }
|
|
tdef.write;
|
|
writedefref(definition);
|
|
current_ppu^.writeentry(ibclassrefdef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tclassrefdef.stabstring : pchar;
|
|
begin
|
|
stabstring:=strpnew('');
|
|
end;
|
|
|
|
|
|
procedure tclassrefdef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{***************************************************************************
|
|
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);
|
|
begin
|
|
inherited init;
|
|
deftype:=setdef;
|
|
setof:=s;
|
|
{$ifdef usesmallset}
|
|
{ small sets only working for i386 PM }
|
|
if high<32 then
|
|
begin
|
|
settype:=smallset;
|
|
savesize:=Sizeof(longint);
|
|
end
|
|
else
|
|
{$endif usesmallset}
|
|
if high<256 then
|
|
begin
|
|
settype:=normset;
|
|
savesize:=32;
|
|
end
|
|
else
|
|
{$ifdef testvarsets}
|
|
if high<$10000 then
|
|
begin
|
|
settype:=varset;
|
|
savesize:=4*((high+31) div 32);
|
|
end
|
|
else
|
|
{$endif testvarsets}
|
|
Message(sym_e_ill_type_decl_set);
|
|
end;
|
|
|
|
|
|
constructor tsetdef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=setdef;
|
|
setof:=readdefref;
|
|
settype:=tsettype(readbyte);
|
|
case settype of
|
|
normset : savesize:=32;
|
|
varset : savesize:=readlong;
|
|
smallset : savesize:=Sizeof(longint);
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tsetdef.write;
|
|
begin
|
|
inherited write;
|
|
writedefref(setof);
|
|
writebyte(byte(settype));
|
|
if settype=varset then
|
|
writelong(savesize);
|
|
current_ppu^.writeentry(ibsetdef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tsetdef.stabstring : pchar;
|
|
begin
|
|
stabstring := strpnew('S'+setof^.numberstring);
|
|
end;
|
|
|
|
|
|
procedure tsetdef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
if ( not assigned(sym) or sym^.isusedinstab or use_dbx) and
|
|
not is_def_stab_written then
|
|
begin
|
|
if assigned(setof) then
|
|
forcestabto(asmlist,setof);
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
procedure tsetdef.deref;
|
|
begin
|
|
resolvedef(setof);
|
|
end;
|
|
|
|
|
|
procedure tsetdef.write_rtti_data;
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(tkSet)));
|
|
rttilist^.concat(new(pai_const,init_8bit(otULong)));
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(lab2str(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;
|
|
|
|
|
|
{***************************************************************************
|
|
TFORMALDEF
|
|
***************************************************************************}
|
|
|
|
constructor tformaldef.init;
|
|
begin
|
|
inherited init;
|
|
deftype:=formaldef;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
constructor tformaldef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=formaldef;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
procedure tformaldef.write;
|
|
begin
|
|
inherited write;
|
|
current_ppu^.writeentry(ibformaldef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tformaldef.stabstring : pchar;
|
|
begin
|
|
stabstring := strpnew('formal'+numberstring+';');
|
|
end;
|
|
|
|
|
|
procedure tformaldef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
{ formaldef can't be stab'ed !}
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{***************************************************************************
|
|
TARRAYDEF
|
|
***************************************************************************}
|
|
|
|
constructor tarraydef.init(l,h : longint;rd : pdef);
|
|
begin
|
|
inherited init;
|
|
deftype:=arraydef;
|
|
lowrange:=l;
|
|
highrange:=h;
|
|
rangedef:=rd;
|
|
definition:=nil;
|
|
IsVariant:=false;
|
|
IsConstructor:=false;
|
|
IsArrayOfConst:=false;
|
|
rangenr:=0;
|
|
end;
|
|
|
|
|
|
constructor tarraydef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=arraydef;
|
|
{ the addresses are calculated later }
|
|
definition:=readdefref;
|
|
rangedef:=readdefref;
|
|
lowrange:=readlong;
|
|
highrange:=readlong;
|
|
IsArrayOfConst:=boolean(readbyte);
|
|
IsVariant:=false;
|
|
IsConstructor:=false;
|
|
rangenr:=0;
|
|
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,init_global(getrangecheckstring)))
|
|
else
|
|
datasegment^.concat(new(pai_symbol,init(getrangecheckstring)));
|
|
datasegment^.concat(new(pai_const,init_32bit(lowrange)));
|
|
datasegment^.concat(new(pai_const,init_32bit(highrange)));
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tarraydef.deref;
|
|
begin
|
|
resolvedef(definition);
|
|
resolvedef(rangedef);
|
|
end;
|
|
|
|
|
|
procedure tarraydef.write;
|
|
begin
|
|
inherited write;
|
|
writedefref(definition);
|
|
writedefref(rangedef);
|
|
writelong(lowrange);
|
|
writelong(highrange);
|
|
writebyte(byte(IsArrayOfConst));
|
|
current_ppu^.writeentry(ibarraydef);
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tarraydef.stabstring : pchar;
|
|
begin
|
|
stabstring := strpnew('ar'+rangedef^.numberstring+';'
|
|
+tostr(lowrange)+';'+tostr(highrange)+';'+definition^.numberstring);
|
|
end;
|
|
|
|
|
|
procedure tarraydef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
if (not assigned(sym) or sym^.isusedinstab or use_dbx)
|
|
and not is_def_stab_written then
|
|
begin
|
|
{when array are inserted they have no definition yet !!}
|
|
if assigned(definition) then
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
function tarraydef.elesize : longint;
|
|
begin
|
|
elesize:=definition^.size;
|
|
end;
|
|
|
|
|
|
function tarraydef.size : longint;
|
|
begin
|
|
size:=(highrange-lowrange+1)*elesize;
|
|
end;
|
|
|
|
|
|
function tarraydef.needs_inittable : boolean;
|
|
begin
|
|
needs_inittable:=definition^.needs_inittable;
|
|
end;
|
|
|
|
|
|
procedure tarraydef.write_child_rtti_table;
|
|
begin
|
|
definition^.get_rtti_label;
|
|
end;
|
|
|
|
|
|
procedure tarraydef.write_rtti_data;
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(13)));
|
|
writename;
|
|
{ size of elements }
|
|
rttilist^.concat(new(pai_const,init_32bit(definition^.size)));
|
|
{ count of elements }
|
|
rttilist^.concat(new(pai_const,init_32bit(highrange-lowrange+1)));
|
|
{ element type }
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(lab2str(definition^.get_rtti_label)))));
|
|
end;
|
|
|
|
|
|
{***************************************************************************
|
|
TRECDEF
|
|
***************************************************************************}
|
|
|
|
constructor trecdef.init(p : psymtable);
|
|
begin
|
|
inherited init;
|
|
deftype:=recorddef;
|
|
symtable:=p;
|
|
savesize:=symtable^.datasize;
|
|
symtable^.defowner := @self;
|
|
end;
|
|
|
|
|
|
constructor trecdef.load;
|
|
var
|
|
oldread_member : boolean;
|
|
begin
|
|
inherited load;
|
|
deftype:=recorddef;
|
|
savesize:=readlong;
|
|
oldread_member:=read_member;
|
|
read_member:=true;
|
|
symtable:=new(psymtable,loadasstruct(recordsymtable));
|
|
read_member:=oldread_member;
|
|
symtable^.defowner := @self;
|
|
end;
|
|
|
|
|
|
destructor trecdef.done;
|
|
begin
|
|
if assigned(symtable) then dispose(symtable,done);
|
|
inherited done;
|
|
end;
|
|
|
|
var
|
|
binittable : boolean;
|
|
|
|
procedure check_rec_inittable(s : psym);
|
|
|
|
begin
|
|
if (s^.typ=varsym) and
|
|
((pvarsym(s)^.definition^.deftype<>objectdef)
|
|
or not(pobjectdef(pvarsym(s)^.definition)^.isclass)) then
|
|
binittable:=pvarsym(s)^.definition^.needs_inittable;
|
|
end;
|
|
|
|
|
|
function trecdef.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(check_rec_inittable);
|
|
needs_inittable:=binittable;
|
|
binittable:=oldb;
|
|
end;
|
|
|
|
|
|
procedure trecdef.deref;
|
|
var
|
|
hp : pdef;
|
|
oldrecsyms : psymtable;
|
|
begin
|
|
oldrecsyms:=aktrecordsymtable;
|
|
aktrecordsymtable:=symtable;
|
|
{ now dereference the definitions }
|
|
hp:=symtable^.rootdef;
|
|
while assigned(hp) do
|
|
begin
|
|
hp^.deref;
|
|
{ set owner }
|
|
hp^.owner:=symtable;
|
|
hp:=hp^.next;
|
|
end;
|
|
{$ifdef tp}
|
|
symtable^.foreach(derefsym);
|
|
{$else}
|
|
symtable^.foreach(@derefsym);
|
|
{$endif}
|
|
aktrecordsymtable:=oldrecsyms;
|
|
end;
|
|
|
|
|
|
procedure trecdef.write;
|
|
var
|
|
oldread_member : boolean;
|
|
begin
|
|
oldread_member:=read_member;
|
|
read_member:=true;
|
|
inherited write;
|
|
writelong(savesize);
|
|
current_ppu^.writeentry(ibrecorddef);
|
|
self.symtable^.writeasstruct;
|
|
read_member:=oldread_member;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
Const StabRecString : pchar = Nil;
|
|
StabRecSize : longint = 0;
|
|
RecOffset : Longint = 0;
|
|
|
|
procedure addname(p : psym);
|
|
var
|
|
news, newrec : pchar;
|
|
spec : string[2];
|
|
begin
|
|
{ static variables from objects are like global objects }
|
|
if ((p^.properties and sp_static)<>0) then
|
|
exit;
|
|
if ((p^.properties and sp_protected)<>0) then
|
|
spec:='/1'
|
|
else if ((p^.properties and sp_private)<>0) then
|
|
spec:='/0'
|
|
else
|
|
spec:='';
|
|
|
|
If p^.typ = varsym then
|
|
begin
|
|
newrec := strpnew(p^.name+':'+spec+pvarsym(p)^.definition^.numberstring
|
|
+','+tostr(pvarsym(p)^.address*8)+','
|
|
+tostr(pvarsym(p)^.definition^.size*8)+';');
|
|
if strlen(StabRecString) + strlen(newrec) >= StabRecSize-256 then
|
|
begin
|
|
getmem(news,stabrecsize+memsizeinc);
|
|
strcopy(news,stabrecstring);
|
|
freemem(stabrecstring,stabrecsize);
|
|
stabrecsize:=stabrecsize+memsizeinc;
|
|
stabrecstring:=news;
|
|
end;
|
|
strcat(StabRecstring,newrec);
|
|
strdispose(newrec);
|
|
{This should be used for case !!}
|
|
RecOffset := RecOffset + pvarsym(p)^.definition^.size;
|
|
end;
|
|
end;
|
|
|
|
|
|
function trecdef.stabstring : pchar;
|
|
Var oldrec : pchar;
|
|
oldsize : longint;
|
|
cur : psym;
|
|
begin
|
|
oldrec := stabrecstring;
|
|
oldsize:=stabrecsize;
|
|
GetMem(stabrecstring,memsizeinc);
|
|
stabrecsize:=memsizeinc;
|
|
strpcopy(stabRecString,'s'+tostr(savesize));
|
|
RecOffset := 0;
|
|
{$ifdef nonextfield}
|
|
{$ifdef tp}
|
|
symtable^.foreach(addname);
|
|
{$else}
|
|
symtable^.foreach(@addname);
|
|
{$endif}
|
|
{$else nonextfield}
|
|
cur:=symtable^.root;
|
|
while assigned(cur) do
|
|
begin
|
|
addname(cur);
|
|
cur:=cur^.nextsym;
|
|
end;
|
|
{$endif nonextfield}
|
|
{ FPC doesn't want to convert a char to a pchar}
|
|
{ is this a bug ? }
|
|
strpcopy(strend(StabRecString),';');
|
|
stabstring := strnew(StabRecString);
|
|
Freemem(stabrecstring,stabrecsize);
|
|
stabrecstring := oldrec;
|
|
stabrecsize:=oldsize;
|
|
end;
|
|
|
|
|
|
procedure trecdef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
if (not assigned(sym) or sym^.isusedinstab or use_dbx) and
|
|
(not is_def_stab_written) then
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
|
|
{$endif GDB}
|
|
|
|
var
|
|
count : longint;
|
|
procedure count_inittable_fields(sym : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
if (sym^.typ=varsym) and (pvarsym(sym)^.definition^.needs_inittable) then
|
|
inc(count);
|
|
end;
|
|
|
|
|
|
procedure count_fields(sym : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
inc(count);
|
|
end;
|
|
|
|
|
|
procedure write_field_inittable(sym : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
if (sym^.typ=varsym) and pvarsym(sym)^.definition^.needs_inittable then
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(lab2str(pvarsym(sym)^.definition^.get_inittable_label)))));
|
|
rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure write_field_rtti(sym : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(lab2str(pvarsym(sym)^.definition^.get_rtti_label)))));
|
|
rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
|
|
end;
|
|
|
|
|
|
procedure generate_child_inittable(sym : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
if (sym^.typ=varsym) and pvarsym(sym)^.definition^.needs_inittable then
|
|
{ force inittable generation }
|
|
pvarsym(sym)^.definition^.get_inittable_label;
|
|
end;
|
|
|
|
|
|
procedure generate_child_rtti(sym : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
pvarsym(sym)^.definition^.get_rtti_label;
|
|
end;
|
|
|
|
|
|
procedure trecdef.write_child_rtti_data;
|
|
begin
|
|
symtable^.foreach(generate_child_rtti);
|
|
end;
|
|
|
|
|
|
procedure trecdef.write_child_init_data;
|
|
begin
|
|
symtable^.foreach(generate_child_inittable);
|
|
end;
|
|
|
|
|
|
procedure trecdef.write_rtti_data;
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(14)));
|
|
writename;
|
|
rttilist^.concat(new(pai_const,init_32bit(size)));
|
|
count:=0;
|
|
symtable^.foreach(count_fields);
|
|
rttilist^.concat(new(pai_const,init_32bit(count)));
|
|
symtable^.foreach(write_field_rtti);
|
|
end;
|
|
|
|
|
|
procedure trecdef.write_init_data;
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_8bit(14)));
|
|
writename;
|
|
rttilist^.concat(new(pai_const,init_32bit(size)));
|
|
count:=0;
|
|
symtable^.foreach(count_inittable_fields);
|
|
rttilist^.concat(new(pai_const,init_32bit(count)));
|
|
symtable^.foreach(write_field_inittable);
|
|
end;
|
|
|
|
|
|
{***************************************************************************
|
|
TABSTRACTPROCDEF
|
|
***************************************************************************}
|
|
|
|
constructor tabstractprocdef.init;
|
|
|
|
begin
|
|
inherited init;
|
|
para1:=nil;
|
|
fpu_used:=0;
|
|
options:=0;
|
|
retdef:=voiddef;
|
|
savesize:=target_os.size_of_pointer;
|
|
end;
|
|
|
|
|
|
|
|
procedure disposepdefcoll(var para1 : pdefcoll);
|
|
var
|
|
hp : pdefcoll;
|
|
begin
|
|
hp:=para1;
|
|
while assigned(hp) do
|
|
begin
|
|
para1:=hp^.next;
|
|
dispose(hp);
|
|
hp:=para1;
|
|
end;
|
|
end;
|
|
|
|
destructor tabstractprocdef.done;
|
|
begin
|
|
disposepdefcoll(para1);
|
|
inherited done;
|
|
end;
|
|
|
|
|
|
procedure tabstractprocdef.concatdef(p : pdef;vsp : tvarspez);
|
|
var
|
|
hp : pdefcoll;
|
|
begin
|
|
new(hp);
|
|
hp^.paratyp:=vsp;
|
|
hp^.data:=p;
|
|
hp^.next:=para1;
|
|
para1:=hp;
|
|
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 assigned(retdef) and is_fpu(retdef) then
|
|
fpu_used:=2;
|
|
end;
|
|
|
|
procedure tabstractprocdef.deref;
|
|
var
|
|
hp : pdefcoll;
|
|
begin
|
|
inherited deref;
|
|
resolvedef(retdef);
|
|
hp:=para1;
|
|
while assigned(hp) do
|
|
begin
|
|
resolvedef(hp^.data);
|
|
hp:=hp^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
constructor tabstractprocdef.load;
|
|
var
|
|
last,hp : pdefcoll;
|
|
count,i : word;
|
|
begin
|
|
inherited load;
|
|
retdef:=readdefref;
|
|
fpu_used:=readbyte;
|
|
options:=readlong;
|
|
count:=readword;
|
|
para1:=nil;
|
|
savesize:=target_os.size_of_pointer;
|
|
for i:=1 to count do
|
|
begin
|
|
new(hp);
|
|
hp^.paratyp:=tvarspez(readbyte);
|
|
hp^.data:=readdefref;
|
|
hp^.next:=nil;
|
|
if para1=nil then
|
|
para1:=hp
|
|
else
|
|
last^.next:=hp;
|
|
last:=hp;
|
|
end;
|
|
end;
|
|
|
|
|
|
function tabstractprocdef.para_size : longint;
|
|
var
|
|
pdc : pdefcoll;
|
|
l : longint;
|
|
begin
|
|
l:=0;
|
|
pdc:=para1;
|
|
while assigned(pdc) do
|
|
begin
|
|
case pdc^.paratyp of
|
|
vs_value : inc(l,align(pdc^.data^.size,target_os.stackalignment));
|
|
vs_var : inc(l,target_os.size_of_pointer);
|
|
vs_const : if dont_copy_const_param(pdc^.data) then
|
|
inc(l,target_os.size_of_pointer)
|
|
else
|
|
inc(l,align(pdc^.data^.size,target_os.stackalignment));
|
|
end;
|
|
pdc:=pdc^.next;
|
|
end;
|
|
para_size:=l;
|
|
end;
|
|
|
|
|
|
procedure tabstractprocdef.write;
|
|
var
|
|
count : word;
|
|
hp : pdefcoll;
|
|
begin
|
|
inherited write;
|
|
writedefref(retdef);
|
|
writebyte(fpu_used);
|
|
writelong(options);
|
|
hp:=para1;
|
|
count:=0;
|
|
while assigned(hp) do
|
|
begin
|
|
inc(count);
|
|
hp:=hp^.next;
|
|
end;
|
|
writeword(count);
|
|
hp:=para1;
|
|
while assigned(hp) do
|
|
begin
|
|
writebyte(byte(hp^.paratyp));
|
|
writedefref(hp^.data);
|
|
hp:=hp^.next;
|
|
end;
|
|
end;
|
|
|
|
|
|
function tabstractprocdef.demangled_paras : string;
|
|
var s : string;
|
|
p : pdefcoll;
|
|
begin
|
|
s:='';
|
|
p:=para1;
|
|
if assigned(p) then
|
|
begin
|
|
s:=s+'(';
|
|
while assigned(p) do
|
|
begin
|
|
if assigned(p^.data^.sym) then
|
|
s:=s+p^.data^.sym^.name
|
|
else if p^.paratyp=vs_var then
|
|
s:=s+'var'
|
|
else if p^.paratyp=vs_const then
|
|
s:=s+'const';
|
|
p:=p^.next;
|
|
if assigned(p) then
|
|
s:=s+','
|
|
else
|
|
s:=s+')';
|
|
end;
|
|
end;
|
|
demangled_paras:=s;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function tabstractprocdef.stabstring : pchar;
|
|
begin
|
|
stabstring := strpnew('abstractproc'+numberstring+';');
|
|
end;
|
|
|
|
|
|
procedure tabstractprocdef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
if (not assigned(sym) or sym^.isusedinstab or use_dbx)
|
|
and not is_def_stab_written then
|
|
begin
|
|
if assigned(retdef) then forcestabto(asmlist,retdef);
|
|
inherited concatstabto(asmlist);
|
|
end;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
{***************************************************************************
|
|
TPROCDEF
|
|
***************************************************************************}
|
|
|
|
constructor tprocdef.init;
|
|
begin
|
|
inherited init;
|
|
deftype:=procdef;
|
|
_mangledname:=nil;
|
|
nextoverloaded:=nil;
|
|
extnumber:=-1;
|
|
localst:=new(psymtable,init(localsymtable));
|
|
parast:=new(psymtable,init(parasymtable));
|
|
{ this is used by insert
|
|
to check same names in parast and localst }
|
|
localst^.next:=parast;
|
|
{$ifdef UseBrowser}
|
|
defref:=nil;
|
|
lastwritten:=nil;
|
|
refcount:=0;
|
|
if (cs_browser in aktmoduleswitches) and make_ref then
|
|
begin
|
|
defref:=new(pref,init(defref,@tokenpos));
|
|
inc(refcount);
|
|
end;
|
|
lastref:=defref;
|
|
{$endif UseBrowser}
|
|
{ first, we assume, that all registers are used }
|
|
{$ifdef i386}
|
|
usedregisters:=$ff;
|
|
{$endif i386}
|
|
{$ifdef m68k}
|
|
usedregisters:=$FFFF;
|
|
{$endif}
|
|
{$ifdef alpha}
|
|
usedregisters_int:=$ffffffff;
|
|
usedregisters_fpu:=$ffffffff;
|
|
{$endif alpha}
|
|
forwarddef:=true;
|
|
_class := nil;
|
|
code:=nil;
|
|
end;
|
|
|
|
|
|
constructor tprocdef.load;
|
|
var
|
|
s : string;
|
|
begin
|
|
inherited load;
|
|
deftype:=procdef;
|
|
{$ifdef i386}
|
|
usedregisters:=readbyte;
|
|
{$endif i386}
|
|
{$ifdef m68k}
|
|
usedregisters:=readword;
|
|
{$endif}
|
|
{$ifdef alpha}
|
|
usedregisters_int:=readlong;
|
|
usedregisters_fpu:=readlong;
|
|
{$endif alpha}
|
|
|
|
s:=readstring;
|
|
setstring(_mangledname,s);
|
|
|
|
|
|
|
|
extnumber:=readlong;
|
|
nextoverloaded:=pprocdef(readdefref);
|
|
_class := pobjectdef(readdefref);
|
|
|
|
if (cs_link_deffile in aktglobalswitches) and ((options and poexports)<>0) then
|
|
deffile.AddExport(mangledname);
|
|
|
|
parast:=nil;
|
|
localst:=nil;
|
|
forwarddef:=false;
|
|
{$ifdef UseBrowser}
|
|
lastref:=nil;
|
|
lastwritten:=nil;
|
|
defref:=nil;
|
|
refcount:=0;
|
|
{$endif UseBrowser}
|
|
end;
|
|
|
|
|
|
{$ifdef UseBrowser}
|
|
procedure tprocdef.load_references;
|
|
var
|
|
pos : tfileposinfo;
|
|
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 then
|
|
begin
|
|
new(parast,load);
|
|
parast^.load_browser;
|
|
new(localst,load);
|
|
localst^.load_browser;
|
|
end;
|
|
end;
|
|
|
|
|
|
function tprocdef.write_references : boolean;
|
|
var
|
|
ref : pref;
|
|
move_last : boolean;
|
|
begin
|
|
move_last:=lastwritten=lastref;
|
|
if move_last and ((current_module^.flags and uf_local_browser)=0) 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 then
|
|
begin
|
|
{ we need dummy para and local symtables
|
|
PPU files are then easier to read PM }
|
|
if not assigned(parast) then
|
|
parast:=new(psymtable,init(parasymtable));
|
|
parast^.write;
|
|
parast^.write_browser;
|
|
if not assigned(localst) then
|
|
localst:=new(psymtable,init(localsymtable));
|
|
localst^.write;
|
|
localst^.write_browser;
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure tprocdef.add_to_browserlog;
|
|
begin
|
|
if assigned(defref) then
|
|
begin
|
|
Browse.AddLog('***'+mangledname);
|
|
Browse.AddLogRefs(defref);
|
|
if (current_module^.flags and uf_local_browser)<>0 then
|
|
begin
|
|
if assigned(parast) then
|
|
parast^.writebrowserlog;
|
|
if assigned(localst) then
|
|
localst^.writebrowserlog;
|
|
end;
|
|
end;
|
|
end;
|
|
{$endif UseBrowser}
|
|
|
|
|
|
destructor tprocdef.done;
|
|
begin
|
|
{$ifdef UseBrowser}
|
|
if assigned(defref) then
|
|
dispose(defref,done);
|
|
{$endif UseBrowser}
|
|
if assigned(parast) then
|
|
dispose(parast,done);
|
|
if assigned(localst) then
|
|
dispose(localst,done);
|
|
if assigned(code) and ((options and poinline) <> 0) then
|
|
disposetree(ptree(code));
|
|
if
|
|
{$ifdef tp}
|
|
not(use_big) and
|
|
{$endif}
|
|
assigned(_mangledname) then
|
|
strdispose(_mangledname);
|
|
inherited done;
|
|
end;
|
|
|
|
|
|
procedure tprocdef.write;
|
|
begin
|
|
inherited write;
|
|
{$ifdef i386}
|
|
writebyte(usedregisters);
|
|
{$endif i386}
|
|
{$ifdef m68k}
|
|
writeword(usedregisters);
|
|
{$endif}
|
|
{$ifdef alpha}
|
|
writelong(usedregisters_int);
|
|
writelong(usedregisters_fpu);
|
|
{$endif alpha}
|
|
writestring(mangledname);
|
|
writelong(extnumber);
|
|
if (options and pooperator) = 0 then
|
|
writedefref(nextoverloaded)
|
|
else
|
|
begin
|
|
{ only write the overloads from the same unit }
|
|
if nextoverloaded^.owner=owner then
|
|
writedefref(nextoverloaded)
|
|
else
|
|
writedefref(nil);
|
|
end;
|
|
writedefref(_class);
|
|
if (options and poinline) <> 0 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;
|
|
|
|
|
|
{$ifdef GDB}
|
|
procedure addparaname(p : psym);
|
|
var vs : char;
|
|
begin
|
|
if pvarsym(p)^.varspez = vs_value then vs := '1'
|
|
else vs := '0';
|
|
strpcopy(strend(StabRecString),p^.name+':'+pvarsym(p)^.definition^.numberstring+','+vs+';');
|
|
end;
|
|
|
|
|
|
function tprocdef.stabstring : pchar;
|
|
var param : pdefcoll;
|
|
i : word;
|
|
vartyp : char;
|
|
oldrec : pchar;
|
|
begin
|
|
oldrec := stabrecstring;
|
|
getmem(StabRecString,1024);
|
|
param := para1;
|
|
i := 0;
|
|
while assigned(param) do
|
|
begin
|
|
inc(i);
|
|
param := param^.next;
|
|
end;
|
|
strpcopy(StabRecString,'f'+retdef^.numberstring);
|
|
if i>0 then
|
|
begin
|
|
strpcopy(strend(StabRecString),','+tostr(i)+';');
|
|
(* confuse gdb !! PM
|
|
if assigned(parast) then
|
|
{$IfDef TP}
|
|
parast^.foreach(addparaname)
|
|
{$Else}
|
|
parast^.foreach(@addparaname)
|
|
{$EndIf}
|
|
else
|
|
begin
|
|
param := para1;
|
|
i := 0;
|
|
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 !!}
|
|
{using lower case parameters }
|
|
strpcopy(strend(stabrecstring),'p'+tostr(i)
|
|
+':'+param^.data^.numberstring+','+vartyp+';');
|
|
param := param^.next;
|
|
end;
|
|
end; *)
|
|
{strpcopy(strend(StabRecString),';');}
|
|
end;
|
|
stabstring := strnew(stabrecstring);
|
|
freemem(stabrecstring,1024);
|
|
stabrecstring := oldrec;
|
|
end;
|
|
|
|
|
|
procedure tprocdef.concatstabto(asmlist : paasmoutput);
|
|
begin
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
procedure tprocdef.deref;
|
|
begin
|
|
inherited deref;
|
|
resolvedef(pdef(nextoverloaded));
|
|
resolvedef(pdef(_class));
|
|
end;
|
|
|
|
|
|
function tprocdef.mangledname : string;
|
|
{$ifdef tp}
|
|
var
|
|
oldpos : longint;
|
|
s : string;
|
|
b : byte;
|
|
{$endif tp}
|
|
begin
|
|
{$ifdef tp}
|
|
if use_big then
|
|
begin
|
|
symbolstream.seek(longint(_mangledname));
|
|
symbolstream.read(b,1);
|
|
symbolstream.read(s[1],b);
|
|
s[0]:=chr(b);
|
|
mangledname:=s;
|
|
end
|
|
else
|
|
{$endif}
|
|
mangledname:=strpas(_mangledname);
|
|
end;
|
|
|
|
|
|
{$IfDef GDB}
|
|
function tprocdef.cplusplusmangledname : string;
|
|
var
|
|
s,s2 : string;
|
|
param : pdefcoll;
|
|
begin
|
|
s := sym^.name;
|
|
if _class <> nil then
|
|
begin
|
|
s2 := _class^.name^;
|
|
s := s+'__'+tostr(length(s2))+s2;
|
|
end else s := s + '_';
|
|
param := para1;
|
|
while assigned(param) do
|
|
begin
|
|
s2 := param^.data^.sym^.name;
|
|
s := s+tostr(length(s2))+s2;
|
|
param := param^.next;
|
|
end;
|
|
cplusplusmangledname:=s;
|
|
end;
|
|
{$EndIf GDB}
|
|
|
|
|
|
procedure tprocdef.setmangledname(const s : string);
|
|
begin
|
|
if {$ifdef tp}not(use_big) and{$endif} (assigned(_mangledname)) then
|
|
strdispose(_mangledname);
|
|
setstring(_mangledname,s);
|
|
{$ifdef UseBrowser}
|
|
if assigned(parast) then
|
|
begin
|
|
stringdispose(parast^.name);
|
|
parast^.name:=stringdup('args of '+s);
|
|
end;
|
|
if assigned(localst) then
|
|
begin
|
|
stringdispose(localst^.name);
|
|
localst^.name:=stringdup('locals of '+s);
|
|
end;
|
|
{$endif UseBrowser}
|
|
end;
|
|
|
|
|
|
{***************************************************************************
|
|
TPROCVARDEF
|
|
***************************************************************************}
|
|
|
|
constructor tprocvardef.init;
|
|
begin
|
|
inherited init;
|
|
deftype:=procvardef;
|
|
end;
|
|
|
|
|
|
constructor tprocvardef.load;
|
|
begin
|
|
inherited load;
|
|
deftype:=procvardef;
|
|
end;
|
|
|
|
|
|
procedure tprocvardef.write;
|
|
begin
|
|
{ here we cannot get a real good value so just give something }
|
|
{ plausible (PM) }
|
|
{ a more secure way would be
|
|
to allways store in a temp }
|
|
if is_fpu(retdef) then
|
|
fpu_used:=2
|
|
else
|
|
fpu_used:=0;
|
|
inherited write;
|
|
current_ppu^.writeentry(ibprocvardef);
|
|
end;
|
|
|
|
|
|
function tprocvardef.size : longint;
|
|
begin
|
|
if (options and pomethodpointer)=0 then
|
|
size:=target_os.size_of_pointer
|
|
else
|
|
size:=2*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);
|
|
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 use_dbx)
|
|
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:=(options and pomethodpointer)<>0;
|
|
end;
|
|
|
|
|
|
{***************************************************************************
|
|
TOBJECTDEF
|
|
***************************************************************************}
|
|
|
|
{$ifdef GDB}
|
|
const
|
|
vtabletype : word = 0;
|
|
vtableassigned : boolean = false;
|
|
{$endif GDB}
|
|
|
|
constructor tobjectdef.init(const n : string;c : pobjectdef);
|
|
begin
|
|
tdef.init;
|
|
deftype:=objectdef;
|
|
options:=0;
|
|
publicsyms:=new(psymtable,init(objectsymtable));
|
|
publicsyms^.name := stringdup(n);
|
|
{ create space for vmt !! }
|
|
{$ifdef OLDVMTSTYLE}
|
|
publicsyms^.datasize:=target_os.size_of_pointer;
|
|
options:=oo_hasvmt;
|
|
vmt_offset:=0;
|
|
{$else }
|
|
options:=0;
|
|
vmt_offset:=0;
|
|
publicsyms^.datasize:=0;
|
|
{$endif }
|
|
publicsyms^.defowner:=@self;
|
|
set_parent(c);
|
|
name:=stringdup(n);
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.set_parent( c : pobjectdef);
|
|
begin
|
|
{ nothing to do if the parent was not forward !}
|
|
if assigned(childof) then
|
|
exit;
|
|
childof:=c;
|
|
{ some options are inherited !! }
|
|
if assigned(c) then
|
|
begin
|
|
options:= options or (c^.options and
|
|
(oo_hasvirtual or oo_hasprivate or
|
|
oo_hasprotected or
|
|
oo_hasconstructor or oo_hasdestructor
|
|
));
|
|
{ add the data of the anchestor class }
|
|
publicsyms^.datasize:=publicsyms^.datasize
|
|
+childof^.publicsyms^.datasize;
|
|
if ((options and oo_hasvmt)<>0) and
|
|
((c^.options and oo_hasvmt)<>0) 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 ((c^.options and oo_hasvmt)<>0) then
|
|
begin
|
|
vmt_offset:=c^.vmt_offset;
|
|
options:=options or oo_hasvmt;
|
|
end;
|
|
end;
|
|
savesize := publicsyms^.datasize;
|
|
end;
|
|
|
|
constructor tobjectdef.load;
|
|
var
|
|
oldread_member : boolean;
|
|
begin
|
|
tdef.load;
|
|
deftype:=objectdef;
|
|
savesize:=readlong;
|
|
vmt_offset:=readlong;
|
|
name:=stringdup(readstring);
|
|
childof:=pobjectdef(readdefref);
|
|
options:=readlong;
|
|
oldread_member:=read_member;
|
|
read_member:=true;
|
|
object_options:=true;
|
|
publicsyms:=new(psymtable,loadasstruct(objectsymtable));
|
|
object_options:=false;
|
|
read_member:=oldread_member;
|
|
publicsyms^.defowner:=@self;
|
|
{ publicsyms^.datasize:=savesize; }
|
|
publicsyms^.name := stringdup(name^);
|
|
|
|
{ handles the predefined class tobject }
|
|
{ the last TOBJECT which is loaded gets }
|
|
{ it ! }
|
|
if (name^='TOBJECT') and not(cs_compilesystem in aktmoduleswitches) and
|
|
isclass and (childof=pointer($ffffffff)) then
|
|
class_tobject:=@self;
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.insertvmt;
|
|
begin
|
|
if (options and oo_hasvmt)<>0 then
|
|
internalerror(12345)
|
|
else
|
|
begin
|
|
{ first round up to multiple of 4 }
|
|
if (aktpackrecords=2) then
|
|
begin
|
|
if (publicsyms^.datasize and 1)<>0 then
|
|
inc(publicsyms^.datasize);
|
|
end;
|
|
if (aktpackrecords>=4) then
|
|
begin
|
|
if (publicsyms^.datasize mod 4) <> 0 then
|
|
publicsyms^.datasize:=publicsyms^.datasize+4-(publicsyms^.datasize mod 4);
|
|
end;
|
|
vmt_offset:=publicsyms^.datasize;
|
|
publicsyms^.datasize:=publicsyms^.datasize+target_os.size_of_pointer;
|
|
options:=options or oo_hasvmt;
|
|
end;
|
|
end;
|
|
|
|
procedure tobjectdef.check_forwards;
|
|
begin
|
|
publicsyms^.check_forwards;
|
|
if (options and oo_isforward)<>0 then
|
|
begin
|
|
{ ok, in future, the forward can be resolved }
|
|
Message1(sym_e_class_forward_not_resolved,name^);
|
|
options:=options and not(oo_isforward);
|
|
end;
|
|
end;
|
|
|
|
|
|
destructor tobjectdef.done;
|
|
begin
|
|
{!!!!
|
|
if assigned(privatesyms) then
|
|
dispose(privatesyms,done);
|
|
if assigned(protectedsyms) then
|
|
dispose(protectedsyms,done); }
|
|
if assigned(publicsyms) then
|
|
dispose(publicsyms,done);
|
|
if (options and oo_isforward)<>0 then
|
|
Message1(sym_e_class_forward_not_resolved,name^);
|
|
stringdispose(name);
|
|
tdef.done;
|
|
end;
|
|
|
|
|
|
{ true, if self inherits from d (or if they are equal) }
|
|
function tobjectdef.isrelated(d : pobjectdef) : boolean;
|
|
var
|
|
hp : pobjectdef;
|
|
begin
|
|
hp:=@self;
|
|
while assigned(hp) do
|
|
begin
|
|
if hp=d then
|
|
begin
|
|
isrelated:=true;
|
|
exit;
|
|
end;
|
|
hp:=hp^.childof;
|
|
end;
|
|
isrelated:=false;
|
|
end;
|
|
|
|
|
|
function tobjectdef.size : longint;
|
|
begin
|
|
if (options and oo_is_class)<>0 then
|
|
size:=target_os.size_of_pointer
|
|
|
|
else
|
|
size:=publicsyms^.datasize;
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.deref;
|
|
var
|
|
hp : pdef;
|
|
oldrecsyms : psymtable;
|
|
begin
|
|
resolvedef(pdef(childof));
|
|
oldrecsyms:=aktrecordsymtable;
|
|
aktrecordsymtable:=publicsyms;
|
|
{ nun die Definitionen dereferenzieren }
|
|
hp:=publicsyms^.rootdef;
|
|
while assigned(hp) do
|
|
begin
|
|
hp^.deref;
|
|
|
|
{ set owner }
|
|
hp^.owner:=publicsyms;
|
|
|
|
hp:=hp^.next;
|
|
end;
|
|
{$ifdef tp}
|
|
publicsyms^.foreach(derefsym);
|
|
{$else}
|
|
publicsyms^.foreach(@derefsym);
|
|
{$endif}
|
|
aktrecordsymtable:=oldrecsyms;
|
|
end;
|
|
|
|
|
|
function tobjectdef.vmt_mangledname : string;
|
|
{DM: I get a nil pointer on the owner name. I don't know if this
|
|
mayhappen, and I have therefore fixed the problem by doing nil pointer
|
|
checks.}
|
|
var
|
|
s1,s2:string;
|
|
begin
|
|
if (options and oo_hasvmt)=0 then
|
|
internalerror(12346);
|
|
if owner^.name=nil then
|
|
s1:=''
|
|
else
|
|
s1:=owner^.name^;
|
|
if name=nil then
|
|
s2:=''
|
|
else
|
|
s2:=name^;
|
|
vmt_mangledname:='VMT_'+s1+'$_'+s2;
|
|
end;
|
|
|
|
|
|
function tobjectdef.rtti_name : string;
|
|
var
|
|
s1,s2:string;
|
|
begin
|
|
if owner^.name=nil then
|
|
s1:=''
|
|
else
|
|
s1:=owner^.name^;
|
|
if name=nil then
|
|
s2:=''
|
|
else
|
|
s2:=name^;
|
|
rtti_name:='RTTI_'+s1+'$_'+s2;
|
|
end;
|
|
|
|
|
|
function tobjectdef.isclass : boolean;
|
|
begin
|
|
isclass:=(options and oo_is_class)<>0;
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.write;
|
|
var
|
|
oldread_member : boolean;
|
|
begin
|
|
tdef.write;
|
|
writelong(size);
|
|
writelong(vmt_offset);
|
|
writestring(name^);
|
|
writedefref(childof);
|
|
writelong(options);
|
|
current_ppu^.writeentry(ibobjectdef);
|
|
|
|
oldread_member:=read_member;
|
|
read_member:=true;
|
|
object_options:=true;
|
|
publicsyms^.writeasstruct;
|
|
object_options:=false;
|
|
read_member:=oldread_member;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
procedure addprocname(p :psym);
|
|
var virtualind,argnames : string;
|
|
news, newrec : pchar;
|
|
pd,ipd : pprocdef;
|
|
lindex : longint;
|
|
para : pdefcoll;
|
|
arglength : byte;
|
|
sp : char;
|
|
|
|
begin
|
|
If p^.typ = procsym then
|
|
begin
|
|
pd := pprocsym(p)^.definition;
|
|
{ this will be used for full implementation of object stabs
|
|
not yet done }
|
|
ipd := pd;
|
|
while assigned(ipd^.nextoverloaded) do ipd := ipd^.nextoverloaded;
|
|
if (pd^.options and povirtualmethod) <> 0 then
|
|
begin
|
|
lindex := pd^.extnumber;
|
|
{doesnt seem to be necessary
|
|
lindex := lindex or $80000000;}
|
|
virtualind := '*'+tostr(lindex)+';'+ipd^._class^.numberstring+';'
|
|
end else virtualind := '.';
|
|
{ arguments are not listed here }
|
|
{we don't need another definition}
|
|
para := pd^.para1;
|
|
argnames := '';
|
|
while assigned(para) do
|
|
begin
|
|
if para^.data^.deftype = formaldef then
|
|
begin
|
|
if para^.paratyp=vs_var then
|
|
argnames := argnames+'3var'
|
|
else if para^.paratyp=vs_const then
|
|
argnames:=argnames+'5const';
|
|
end
|
|
else
|
|
begin
|
|
{ if the arg definition is like (v: ^byte;..
|
|
there is no sym attached to data !!! }
|
|
if assigned(para^.data^.sym) then
|
|
begin
|
|
arglength := length(para^.data^.sym^.name);
|
|
argnames := argnames + tostr(arglength)+para^.data^.sym^.name;
|
|
end
|
|
else
|
|
begin
|
|
argnames:=argnames+'11unnamedtype';
|
|
end;
|
|
end;
|
|
para := para^.next;
|
|
end;
|
|
ipd^.is_def_stab_written := true;
|
|
{ here 2A must be changed for private and protected }
|
|
{ 0 is private 1 protected and 2 public }
|
|
if (p^.properties and sp_private)<>0 then sp:='0'
|
|
else if (p^.properties and sp_protected)<>0 then sp:='1'
|
|
else sp:='2';
|
|
newrec := strpnew(p^.name+'::'+ipd^.numberstring
|
|
+'=##'+pd^.retdef^.numberstring+';:'+argnames+';'+sp+'A'
|
|
+virtualind+';');
|
|
{ get spare place for a string at the end }
|
|
if strlen(StabRecString) + strlen(newrec) >= StabRecSize-256 then
|
|
begin
|
|
getmem(news,stabrecsize+memsizeinc);
|
|
strcopy(news,stabrecstring);
|
|
freemem(stabrecstring,stabrecsize);
|
|
stabrecsize:=stabrecsize+memsizeinc;
|
|
stabrecstring:=news;
|
|
end;
|
|
strcat(StabRecstring,newrec);
|
|
{freemem(newrec,memsizeinc); }
|
|
strdispose(newrec);
|
|
{This should be used for case !!}
|
|
RecOffset := RecOffset + pd^.size;
|
|
end;
|
|
end;
|
|
|
|
|
|
function tobjectdef.stabstring : pchar;
|
|
var anc : pobjectdef;
|
|
oldrec : pchar;
|
|
oldrecsize : longint;
|
|
str_end : string;
|
|
{$ifndef nonextfield}
|
|
cur : psym;
|
|
{$endif nonextfield}
|
|
begin
|
|
oldrec := stabrecstring;
|
|
oldrecsize:=stabrecsize;
|
|
stabrecsize:=memsizeinc;
|
|
GetMem(stabrecstring,stabrecsize);
|
|
strpcopy(stabRecString,'s'+tostr(size));
|
|
if assigned(childof) then
|
|
{only one ancestor not virtual, public, at base offset 0 }
|
|
{ !1 , 0 2 0 , }
|
|
strpcopy(strend(stabrecstring),'!1,020,'+childof^.numberstring+';');
|
|
{virtual table to implement yet}
|
|
RecOffset := 0;
|
|
{$ifdef nonextfield}
|
|
{$ifdef tp}
|
|
publicsyms^.foreach(addname);
|
|
{$else}
|
|
publicsyms^.foreach(@addname);
|
|
{$endif}
|
|
{$else nonextfield}
|
|
cur:=publicsyms^.root;
|
|
while assigned(cur) do
|
|
begin
|
|
addname(cur);
|
|
cur:=cur^.nextsym;
|
|
end;
|
|
{$endif nonextfield}
|
|
if (options and oo_hasvmt) <> 0 then
|
|
if not assigned(childof) or ((childof^.options and oo_hasvmt) = 0) then
|
|
begin
|
|
strpcopy(strend(stabrecstring),'$vf'+numberstring+':'+typeglobalnumber('vtblarray')
|
|
+','+tostr(vmt_offset*8)+';');
|
|
end;
|
|
{$ifdef nonextfield}
|
|
{$ifdef tp}
|
|
publicsyms^.foreach(addprocname);
|
|
{$else}
|
|
publicsyms^.foreach(@addprocname);
|
|
{$endif tp }
|
|
{$else nonextfield}
|
|
cur:=publicsyms^.root;
|
|
while assigned(cur) do
|
|
begin
|
|
addprocname(cur);
|
|
cur:=cur^.nextsym;
|
|
end;
|
|
{$endif nonextfield}
|
|
if (options and oo_hasvmt) <> 0 then
|
|
begin
|
|
anc := @self;
|
|
while assigned(anc^.childof) and ((anc^.childof^.options and oo_hasvmt) <> 0) do
|
|
anc := anc^.childof;
|
|
str_end:=';~%'+anc^.numberstring+';';
|
|
end
|
|
else
|
|
str_end:=';';
|
|
strpcopy(strend(stabrecstring),str_end);
|
|
stabstring := strnew(StabRecString);
|
|
freemem(stabrecstring,stabrecsize);
|
|
stabrecstring := oldrec;
|
|
stabrecsize:=oldrecsize;
|
|
end;
|
|
{$endif GDB}
|
|
|
|
|
|
procedure tobjectdef.write_child_init_data;
|
|
begin
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.write_init_data;
|
|
begin
|
|
if isclass 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(name^))));
|
|
rttilist^.concat(new(pai_string,init(name^)));
|
|
|
|
rttilist^.concat(new(pai_const,init_32bit(size)));
|
|
count:=0;
|
|
publicsyms^.foreach(count_inittable_fields);
|
|
rttilist^.concat(new(pai_const,init_32bit(count)));
|
|
publicsyms^.foreach(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(check_rec_inittable);
|
|
needs_inittable:=binittable;
|
|
binittable:=oldb;
|
|
end;
|
|
|
|
|
|
procedure count_published_properties(sym : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
if (sym^.typ=propertysym) and ((sym^.properties and sp_published)<>0) then
|
|
inc(count);
|
|
end;
|
|
|
|
|
|
procedure write_property_info(sym : psym);{$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 sym^.typ=varsym 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,init_symbol(strpnew(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 (ppropertysym(sym)^.options and ppo_indexed)<>0 then
|
|
proctypesinfo:=$40
|
|
else
|
|
proctypesinfo:=0;
|
|
if (sym^.typ=propertysym) and ((sym^.properties and sp_published)<>0) then
|
|
begin
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(lab2str(ppropertysym(sym)^.proptype^.get_rtti_label)))));
|
|
writeproc(ppropertysym(sym)^.readaccesssym,ppropertysym(sym)^.readaccessdef,0);
|
|
writeproc(ppropertysym(sym)^.writeaccesssym,ppropertysym(sym)^.writeaccessdef,2);
|
|
{ isn't it stored ? }
|
|
if (ppropertysym(sym)^.options and ppo_stored)=0 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 : psym);{$ifndef fpc}far;{$endif}
|
|
begin
|
|
if (sym^.typ=propertysym) and ((sym^.properties and sp_published)<>0) then
|
|
ppropertysym(sym)^.proptype^.get_rtti_label;
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.write_child_rtti_data;
|
|
begin
|
|
publicsyms^.foreach(generate_published_child_rtti);
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.generate_rtti;
|
|
begin
|
|
has_rtti:=true;
|
|
getlabel(rtti_label);
|
|
write_child_rtti_data;
|
|
rttilist^.concat(new(pai_symbol,init_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 assigned(childof) and ((childof^.options and oo_can_have_published)<>0) then
|
|
i:=childof^.next_free_name_index
|
|
else
|
|
i:=0;
|
|
count:=0;
|
|
publicsyms^.foreach(count_published_properties);
|
|
next_free_name_index:=i+count;
|
|
end;
|
|
|
|
|
|
procedure tobjectdef.write_rtti_data;
|
|
begin
|
|
if isclass 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(name^))));
|
|
rttilist^.concat(new(pai_string,init(name^)));
|
|
|
|
{ write class type }
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(vmt_mangledname))));
|
|
|
|
{ write owner typeinfo }
|
|
if assigned(childof) and ((childof^.options and oo_can_have_published)<>0) then
|
|
rttilist^.concat(new(pai_const,init_symbol(strpnew(lab2str(childof^.get_rtti_label)))))
|
|
else
|
|
rttilist^.concat(new(pai_const,init_32bit(0)));
|
|
|
|
{ write published properties count }
|
|
count:=0;
|
|
publicsyms^.foreach(count_published_properties);
|
|
rttilist^.concat(new(pai_const,init_16bit(count)));
|
|
|
|
{ write unit name }
|
|
if assigned(owner^.name) 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)));
|
|
|
|
{ count is used to write nameindex }
|
|
{ but we need an offset of the owner }
|
|
{ to give each property an own slot }
|
|
if assigned(childof) and ((childof^.options and oo_can_have_published)<>0) then
|
|
count:=childof^.next_free_name_index
|
|
else
|
|
count:=0;
|
|
publicsyms^.foreach(write_property_info);
|
|
end;
|
|
|
|
|
|
function tobjectdef.is_publishable : boolean;
|
|
begin
|
|
is_publishable:=isclass;
|
|
end;
|
|
|
|
|
|
{****************************************************************************
|
|
TERRORDEF
|
|
****************************************************************************}
|
|
|
|
constructor terrordef.init;
|
|
begin
|
|
inherited init;
|
|
deftype:=errordef;
|
|
end;
|
|
|
|
|
|
{$ifdef GDB}
|
|
function terrordef.stabstring : pchar;
|
|
begin
|
|
stabstring:=strpnew('error'+numberstring);
|
|
end;
|
|
{$endif GDB}
|
|
|
|
{
|
|
$Log$
|
|
Revision 1.65 1998-10-26 14:19:28 pierre
|
|
+ added options -lS and -lT for source and target os output
|
|
(to have a easier way to test OS_SOURCE abd OS_TARGET in makefiles)
|
|
* several problems with rtti data
|
|
(type of sym was not checked)
|
|
assumed to be varsym when they could be procsym or property syms !!
|
|
|
|
Revision 1.64 1998/10/22 17:11:21 pierre
|
|
+ terminated the include exclude implementation for i386
|
|
* enums inside records fixed
|
|
|
|
Revision 1.63 1998/10/20 09:32:56 peter
|
|
* removed some unused vars
|
|
|
|
Revision 1.62 1998/10/20 08:06:58 pierre
|
|
* several memory corruptions due to double freemem solved
|
|
=> never use p^.loc.location:=p^.left^.loc.location;
|
|
+ finally I added now by default
|
|
that ra386dir translates global and unit symbols
|
|
+ added a first field in tsymtable and
|
|
a nextsym field in tsym
|
|
(this allows to obtain ordered type info for
|
|
records and objects in gdb !)
|
|
|
|
Revision 1.61 1998/10/19 08:55:05 pierre
|
|
* wrong stabs info corrected once again !!
|
|
+ variable vmt offset with vmt field only if required
|
|
implemented now !!!
|
|
|
|
Revision 1.60 1998/10/16 13:12:53 pierre
|
|
* added vmt_offsets in destructors code also !!!
|
|
* vmt_offset code for m68k
|
|
|
|
Revision 1.59 1998/10/16 08:51:51 peter
|
|
+ target_os.stackalignment
|
|
+ stack can be aligned at 2 or 4 byte boundaries
|
|
|
|
Revision 1.58 1998/10/15 15:13:30 pierre
|
|
+ added oo_hasconstructor and oo_hasdestructor
|
|
for objects options
|
|
|
|
Revision 1.57 1998/10/14 15:54:20 pierre
|
|
* smallsets are not entirely implemented for
|
|
m68k added a ifdef usesmallset
|
|
that is allways defined for i386
|
|
(enables testing for m68k)
|
|
|
|
Revision 1.56 1998/10/09 11:47:56 pierre
|
|
* still more memory leaks fixes !!
|
|
|
|
Revision 1.55 1998/10/06 17:16:55 pierre
|
|
* some memory leaks fixed (thanks to Peter for heaptrc !)
|
|
|
|
Revision 1.54 1998/10/05 21:33:28 peter
|
|
* fixed 161,165,166,167,168
|
|
|
|
Revision 1.53 1998/10/05 12:48:39 pierre
|
|
* wrong handling of range check for arrays fixed
|
|
|
|
Revision 1.52 1998/10/02 07:20:38 florian
|
|
* range checking in units doesn't work if the units are smartlinked, fixed
|
|
|
|
Revision 1.51 1998/09/25 12:01:41 florian
|
|
* tobjectdef.publicsyms.datasize was set to savesize, this is wrong now
|
|
because the symtable size is read from the ppu file
|
|
|
|
Revision 1.50 1998/09/23 15:46:40 florian
|
|
* problem with with and classes fixed
|
|
|
|
Revision 1.49 1998/09/23 12:03:55 peter
|
|
* overloading fix for array of const
|
|
|
|
Revision 1.48 1998/09/22 15:37:23 peter
|
|
+ array of const start
|
|
|
|
Revision 1.47 1998/09/21 15:46:01 michael
|
|
Applied florians fix for check_rec_inittable
|
|
|
|
Revision 1.46 1998/09/21 08:45:21 pierre
|
|
+ added vmt_offset in tobjectdef.write for fututre use
|
|
(first steps to have objects without vmt if no virtual !!)
|
|
+ added fpu_used field for tabstractprocdef :
|
|
sets this level to 2 if the functions return with value in FPU
|
|
(is then set to correct value at parsing of implementation)
|
|
THIS MIGHT refuse some code with FPU expression too complex
|
|
that were accepted before and even in some cases
|
|
that don't overflow in fact
|
|
( like if f : float; is a forward that finally in implementation
|
|
only uses one fpu register !!)
|
|
Nevertheless I think that it will improve security on
|
|
FPU operations !!
|
|
* most other changes only for UseBrowser code
|
|
(added symtable references for record and objects)
|
|
local switch for refs to args and local of each function
|
|
(static symtable still missing)
|
|
UseBrowser still not stable and probably broken by
|
|
the definition hash array !!
|
|
|
|
Revision 1.45 1998/09/20 08:31:29 florian
|
|
+ bit 6 of tpropinfo.propprocs is set, if the property contains a
|
|
constant index
|
|
|
|
Revision 1.44 1998/09/19 15:23:58 florian
|
|
* rtti for ordtypes corrected
|
|
|
|
Revision 1.43 1998/09/18 17:12:40 florian
|
|
* problem with writing of class references fixed
|
|
|
|
Revision 1.42 1998/09/17 13:41:20 pierre
|
|
sizeof(TPOINT) problem
|
|
|
|
Revision 1.40.2.2 1998/09/17 08:42:33 pierre
|
|
TPOINT sizeof fix
|
|
|
|
Revision 1.41 1998/09/15 17:39:30 jonas
|
|
+ bugfix from bugfix branch
|
|
|
|
Revision 1.40.2.1 1998/09/15 17:35:32 jonas
|
|
* chenged string_typ in tstringdef.wideload from ansistring to widestring
|
|
|
|
Revision 1.40 1998/09/09 15:34:00 peter
|
|
* removed warnings
|
|
|
|
Revision 1.39 1998/09/08 10:23:44 pierre
|
|
* name field of filedef corrected
|
|
|
|
Revision 1.38 1998/09/07 23:10:23 florian
|
|
* a lot of stuff fixed regarding rtti and publishing of properties,
|
|
basics should now work
|
|
|
|
Revision 1.37 1998/09/07 19:33:24 florian
|
|
+ some stuff for property rtti added:
|
|
- NameIndex of the TPropInfo record is now written correctly
|
|
- the DEFAULT/NODEFAULT keyword is supported now
|
|
- the default value and the storedsym/def are now written to
|
|
the PPU fiel
|
|
|
|
Revision 1.36 1998/09/07 17:37:01 florian
|
|
* first fixes for published properties
|
|
|
|
Revision 1.35 1998/09/06 22:42:02 florian
|
|
+ rtti genreation for properties added
|
|
|
|
Revision 1.34 1998/09/04 18:15:02 peter
|
|
* filedef updated
|
|
|
|
Revision 1.33 1998/09/03 17:08:49 pierre
|
|
* better lines for stabs
|
|
(no scroll back to if before else part
|
|
no return to case line at jump outside case)
|
|
+ source lines also if not in order
|
|
|
|
Revision 1.32 1998/09/03 16:03:20 florian
|
|
+ rtti generation
|
|
* init table generation changed
|
|
|
|
Revision 1.31 1998/09/02 15:14:28 peter
|
|
* enum packing changed from len to max
|
|
|
|
Revision 1.30 1998/09/01 17:37:29 peter
|
|
* removed debug writeln :(
|
|
|
|
Revision 1.29 1998/09/01 12:53:25 peter
|
|
+ aktpackenum
|
|
|
|
Revision 1.28 1998/09/01 07:54:22 pierre
|
|
* UseBrowser a little updated (might still be buggy !!)
|
|
* bug in psub.pas in function specifier removed
|
|
* stdcall allowed in interface and in implementation
|
|
(FPC will not yet complain if it is missing in either part
|
|
because stdcall is only a dummy !!)
|
|
|
|
Revision 1.27 1998/08/28 12:51:43 florian
|
|
+ ansistring to pchar type cast fixed
|
|
|
|
Revision 1.26 1998/08/25 12:42:44 pierre
|
|
* CDECL changed to CVAR for variables
|
|
specifications are read in structures also
|
|
+ started adding GPC compatibility mode ( option -Sp)
|
|
* names changed to lowercase
|
|
|
|
Revision 1.25 1998/08/23 21:04:38 florian
|
|
+ rtti generation for classes added
|
|
+ new/dispose do now also a call to INITIALIZE/FINALIZE, if necessaray
|
|
|
|
Revision 1.24 1998/08/20 12:53:26 peter
|
|
* object_options are always written for object syms
|
|
|
|
Revision 1.23 1998/08/19 00:42:42 peter
|
|
+ subrange types for enums
|
|
+ checking for bounds type with ranges
|
|
|
|
Revision 1.22 1998/08/17 10:10:10 peter
|
|
- removed OLDPPU
|
|
|
|
Revision 1.21 1998/08/10 14:50:28 peter
|
|
+ localswitches, moduleswitches, globalswitches splitting
|
|
|
|
Revision 1.20 1998/07/18 22:54:30 florian
|
|
* some ansi/wide/longstring support fixed:
|
|
o parameter passing
|
|
o returning as result from functions
|
|
|
|
Revision 1.19 1998/07/14 14:47:05 peter
|
|
* released NEWINPUT
|
|
|
|
Revision 1.18 1998/07/10 10:51:04 peter
|
|
* m68k updates
|
|
|
|
Revision 1.16 1998/07/07 11:20:13 peter
|
|
+ NEWINPUT for a better inputfile and scanner object
|
|
|
|
Revision 1.15 1998/06/24 14:48:37 peter
|
|
* ifdef newppu -> ifndef oldppu
|
|
|
|
Revision 1.14 1998/06/16 08:56:31 peter
|
|
+ targetcpu
|
|
* cleaner pmodules for newppu
|
|
|
|
Revision 1.13 1998/06/15 15:38:09 pierre
|
|
* small bug in systems.pas corrected
|
|
+ operators in different units better hanlded
|
|
|
|
Revision 1.12 1998/06/15 14:30:12 daniel
|
|
|
|
* Reverted my changes.
|
|
|
|
Revision 1.10 1998/06/13 00:10:16 peter
|
|
* working browser and newppu
|
|
* some small fixes against crashes which occured in bp7 (but not in
|
|
fpc?!)
|
|
|
|
Revision 1.9 1998/06/12 14:10:37 michael
|
|
* Fixed wrong code for ansistring
|
|
|
|
Revision 1.8 1998/06/11 10:11:58 peter
|
|
* -gb works again
|
|
|
|
Revision 1.7 1998/06/07 15:30:25 florian
|
|
+ first working rtti
|
|
+ data init/final. for local variables
|
|
|
|
Revision 1.6 1998/06/05 14:37:37 pierre
|
|
* fixes for inline for operators
|
|
* inline procedure more correctly restricted
|
|
|
|
Revision 1.5 1998/06/04 23:52:01 peter
|
|
* m68k compiles
|
|
+ .def file creation moved to gendef.pas so it could also be used
|
|
for win32
|
|
|
|
Revision 1.4 1998/06/04 09:55:45 pierre
|
|
* demangled name of procsym reworked to become independant of the mangling
|
|
scheme
|
|
|
|
Revision 1.3 1998/06/03 22:49:03 peter
|
|
+ wordbool,longbool
|
|
* rename bis,von -> high,low
|
|
* moved some systemunit loading/creating to psystem.pas
|
|
|
|
Revision 1.2 1998/05/31 14:13:37 peter
|
|
* fixed call bugs with assembler readers
|
|
+ OPR_SYMBOL to hold a symbol in the asm parser
|
|
* fixed staticsymtable vars which were acessed through %ebp instead of
|
|
name
|
|
|
|
Revision 1.1 1998/05/27 19:45:09 peter
|
|
* symtable.pas splitted into includefiles
|
|
* symtable adapted for $ifndef OLDPPU
|
|
|
|
}
|