3 Copyright (c) 1998-2000 by Florian Klaempfl, Pierre Muller
5 Symbol table implementation for the definitions
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 ****************************************************************************
23 {****************************************************************************
24 TDEF (base class for definitions)
25 ****************************************************************************}
28 { if you change one of the following contants, }
29 { you have also to change the typinfo unit }
30 { and the rtl/i386,template/rttip.inc files }
85 manglenamesize : longint;
88 constructor tdef.init;
96 symtablestack^.registerdef(@self);
100 is_def_stab_written := not_written;
103 if assigned(lastglobaldef) then
105 lastglobaldef^.nextglobal := @self;
106 previousglobal:=lastglobaldef;
110 firstglobaldef := @self;
111 previousglobal := nil;
113 lastglobaldef := @self;
118 constructor tdef.load;
121 deftype:=abstractdef;
124 has_inittable:=false;
126 is_def_stab_written := not_written;
129 if assigned(lastglobaldef) then
131 lastglobaldef^.nextglobal := @self;
132 previousglobal:=lastglobaldef;
136 firstglobaldef := @self;
139 lastglobaldef := @self;
143 typesym:=ptypesym(readsymref);
147 destructor tdef.done;
150 if not(assigned(previousglobal)) then
152 firstglobaldef := nextglobal;
153 if assigned(firstglobaldef) then
154 firstglobaldef^.previousglobal:=nil;
158 { remove reference in the element before }
159 previousglobal^.nextglobal:=nextglobal;
162 if not(assigned(nextglobal)) then
164 lastglobaldef := previousglobal;
165 if assigned(lastglobaldef) then
166 lastglobaldef^.nextglobal:=nil;
169 nextglobal^.previousglobal:=previousglobal;
173 while assigned(typesym) do
175 typesym^.restype.setdef(nil);
176 typesym:=typesym^.synonym;
181 { used for enumdef because the symbols are
182 inserted in the owner symtable }
183 procedure tdef.correct_owner_symtable;
187 if assigned(owner) and
188 (owner^.symtabletype in [recordsymtable,objectsymtable]) then
190 owner^.defindex^.deleteindex(@self);
192 while (st^.symtabletype in [recordsymtable,objectsymtable]) do
194 st^.registerdef(@self);
199 function tdef.typename:string;
201 if assigned(typesym) and not(deftype=procvardef) then
202 typename:=Upper(typesym^.name)
204 typename:=gettypename;
207 function tdef.gettypename : string;
210 gettypename:='<unknown type>'
213 function tdef.is_in_current : boolean;
218 is_in_current:=false;
221 if (p=current_module^.globalsymtable) or (p=current_module^.localsymtable)
222 or (p^.symtabletype in [globalsymtable,staticsymtable]) then
227 else if p^.symtabletype in [localsymtable,parasymtable,objectsymtable] then
229 if assigned(p^.defowner) then
230 p:=pobjectdef(p^.defowner)^.owner
240 procedure tdef.write;
243 writesymref(typesym);
247 if assigned(owner) then
248 globalnb := owner^.getnewtypecount
251 globalnb := PGlobalTypeCount^;
252 Inc(PGlobalTypeCount^);
259 function tdef.size : longint;
265 function tdef.alignment : longint;
267 { normal alignment by default }
273 procedure tdef.set_globalnb;
275 globalnb :=PGlobalTypeCount^;
276 inc(PglobalTypeCount^);
279 function tdef.stabstring : pchar;
281 stabstring := strpnew('t'+numberstring+';');
285 function tdef.numberstring : string;
286 var table : psymtable;
288 {formal def have no type !}
289 if deftype = formaldef then
291 numberstring := voiddef^.numberstring;
294 if (not assigned(typesym)) or (not typesym^.isusedinstab) then
296 {set even if debuglist is not defined}
297 if assigned(typesym) then
298 typesym^.isusedinstab := true;
299 if assigned(debuglist) and (is_def_stab_written = not_written) then
300 concatstabto(debuglist);
302 if not (cs_gdb_dbx in aktglobalswitches) then
306 numberstring := tostr(globalnb);
312 if assigned(owner) then
313 globalnb := owner^.getnewtypecount
316 globalnb := PGlobalTypeCount^;
317 Inc(PGlobalTypeCount^);
320 if assigned(typesym) then
322 table := typesym^.owner;
323 if table^.unitid > 0 then
324 numberstring := '('+tostr(table^.unitid)+','+tostr(typesym^.restype.def^.globalnb)+')'
326 numberstring := tostr(globalnb);
329 numberstring := tostr(globalnb);
334 function tdef.allstabstring : pchar;
335 var stabchar : string[2];
338 sym_line_no : longint;
341 getmem(st,strlen(ss)+512);
343 if deftype in tagtypes then
345 if assigned(typesym) then
347 sname := typesym^.name;
348 sym_line_no:=typesym^.fileinfo.line;
355 strpcopy(st,'"'+sname+':'+stabchar+numberstring+'=');
356 strpcopy(strecopy(strend(st),ss),'",'+tostr(N_LSYM)+',0,'+tostr(sym_line_no)+',0');
357 allstabstring := strnew(st);
358 freemem(st,strlen(ss)+512);
363 procedure tdef.concatstabto(asmlist : paasmoutput);
364 var stab_str : pchar;
366 if ((typesym = nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
367 and (is_def_stab_written = not_written) then
369 If cs_gdb_dbx in aktglobalswitches then
371 { otherwise you get two of each def }
372 If assigned(typesym) then
374 if typesym^.typ=symconst.typesym then
375 typesym^.isusedinstab:=true;
376 if (typesym^.owner = nil) or
377 ((typesym^.owner^.symtabletype = unitsymtable) and
378 punitsymtable(typesym^.owner)^.dbx_count_ok) then
380 {with DBX we get the definition from the other objects }
381 is_def_stab_written := written;
386 { to avoid infinite loops }
387 is_def_stab_written := being_written;
388 stab_str := allstabstring;
389 asmlist^.concat(new(pai_stabs,init(stab_str)));
390 is_def_stab_written := written;
396 procedure tdef.deref;
398 resolvesym(psym(typesym));
403 procedure tdef.generate_rtti;
408 getdatalabel(rtti_label);
409 write_child_rtti_data;
410 rttilist^.concat(new(pai_symbol,init(rtti_label,0)));
412 rttilist^.concat(new(pai_symbol_end,init(rtti_label)));
417 function tdef.get_rtti_label : string;
420 get_rtti_label:=rtti_label^.name;
424 { init table handling }
425 function tdef.needs_inittable : boolean;
427 needs_inittable:=false;
431 procedure tdef.generate_inittable;
434 getdatalabel(inittable_label);
435 write_child_init_data;
436 rttilist^.concat(new(pai_label,init(inittable_label)));
441 procedure tdef.write_init_data;
447 procedure tdef.write_child_init_data;
449 write_child_rtti_data;
453 function tdef.get_inittable_label : pasmlabel;
455 if not(has_inittable) then
457 get_inittable_label:=inittable_label;
461 procedure tdef.write_rtti_name;
466 if assigned(typesym) then
469 rttilist^.concat(new(pai_string,init(chr(length(str))+str)));
472 rttilist^.concat(new(pai_string,init(#0)))
476 { returns true, if the definition can be published }
477 function tdef.is_publishable : boolean;
479 is_publishable:=false;
483 procedure tdef.write_rtti_data;
488 procedure tdef.write_child_rtti_data;
493 function tdef.is_intregable : boolean;
496 is_intregable:=false;
503 case porddef(@self)^.typ of
504 bool8bit,bool16bit,bool32bit,
510 is_intregable:=is_smallset(@self);
514 function tdef.is_fpuregable : boolean;
517 is_fpuregable:=(deftype=floatdef) and not(pfloatdef(@self)^.typ in [f32bit,f16bit]);
520 {****************************************************************************
522 ****************************************************************************}
524 constructor tstringdef.shortinit(l : byte);
527 string_typ:=st_shortstring;
534 constructor tstringdef.shortload;
537 string_typ:=st_shortstring;
544 constructor tstringdef.longinit(l : longint);
547 string_typ:=st_longstring;
550 savesize:=target_os.size_of_pointer;
554 constructor tstringdef.longload;
558 string_typ:=st_longstring;
560 savesize:=target_os.size_of_pointer;
564 constructor tstringdef.ansiinit(l : longint);
567 string_typ:=st_ansistring;
570 savesize:=target_os.size_of_pointer;
574 constructor tstringdef.ansiload;
578 string_typ:=st_ansistring;
580 savesize:=target_os.size_of_pointer;
584 constructor tstringdef.wideinit(l : longint);
587 string_typ:=st_widestring;
590 savesize:=target_os.size_of_pointer;
594 constructor tstringdef.wideload;
598 string_typ:=st_widestring;
600 savesize:=target_os.size_of_pointer;
604 function tstringdef.stringtypname:string;
606 typname:array[tstringtype] of string[8]=('',
607 'SHORTSTR','LONGSTR','ANSISTR','WIDESTR'
610 stringtypname:=typname[string_typ];
614 function tstringdef.size : longint;
620 procedure tstringdef.write;
623 if string_typ=st_shortstring then
628 st_shortstring : current_ppu^.writeentry(ibshortstringdef);
629 st_longstring : current_ppu^.writeentry(iblongstringdef);
630 st_ansistring : current_ppu^.writeentry(ibansistringdef);
631 st_widestring : current_ppu^.writeentry(ibwidestringdef);
637 function tstringdef.stabstring : pchar;
639 bytest,charst,longst : string;
644 charst := typeglobalnumber('char');
645 { this is what I found in stabs.texinfo but
646 gdb 4.12 for go32 doesn't understand that !! }
647 {$IfDef GDBknowsstrings}
648 stabstring := strpnew('n'+charst+';'+tostr(len));
650 bytest := typeglobalnumber('byte');
651 stabstring := strpnew('s'+tostr(len+1)+'length:'+bytest
653 +';1;'+tostr(len)+';'+charst+',8,'+tostr(len*8)+';;');
658 charst := typeglobalnumber('char');
659 { this is what I found in stabs.texinfo but
660 gdb 4.12 for go32 doesn't understand that !! }
661 {$IfDef GDBknowsstrings}
662 stabstring := strpnew('n'+charst+';'+tostr(len));
664 bytest := typeglobalnumber('byte');
665 longst := typeglobalnumber('longint');
666 stabstring := strpnew('s'+tostr(len+5)+'length:'+longst
667 +',0,32;dummy:'+bytest+',32,8;st:ar'+bytest
668 +';1;'+tostr(len)+';'+charst+',40,'+tostr(len*8)+';;');
673 { an ansi string looks like a pchar easy !! }
674 stabstring:=strpnew('*'+typeglobalnumber('char'));
678 { an ansi string looks like a pchar easy !! }
679 stabstring:=strpnew('*'+typeglobalnumber('char'));
685 procedure tstringdef.concatstabto(asmlist : paasmoutput);
687 inherited concatstabto(asmlist);
692 function tstringdef.needs_inittable : boolean;
694 needs_inittable:=string_typ in [st_ansistring,st_widestring];
697 function tstringdef.gettypename : string;
700 names : array[tstringtype] of string[20] = ('',
701 'ShortString','LongString','AnsiString','WideString');
704 gettypename:=names[string_typ];
707 procedure tstringdef.write_rtti_data;
712 rttilist^.concat(new(pai_const,init_8bit(tkAString)));
717 rttilist^.concat(new(pai_const,init_8bit(tkWString)));
722 rttilist^.concat(new(pai_const,init_8bit(tkLString)));
727 rttilist^.concat(new(pai_const,init_8bit(tkSString)));
729 rttilist^.concat(new(pai_const,init_8bit(len)));
735 function tstringdef.is_publishable : boolean;
737 is_publishable:=true;
741 {****************************************************************************
743 ****************************************************************************}
745 constructor tenumdef.init;
756 correct_owner_symtable;
759 constructor tenumdef.init_subrange(_basedef:penumdef;_min,_max:longint);
769 firstenum:=basedef^.firstenum;
770 while assigned(firstenum) and (penumsym(firstenum)^.value<>minval) do
771 firstenum:=firstenum^.nextenum;
772 correct_owner_symtable;
776 constructor tenumdef.load;
780 basedef:=penumdef(readdefref);
789 procedure tenumdef.calcsavesize;
791 if (aktpackenum=4) or (min<0) or (max>65535) then
794 if (aktpackenum=2) or (min<0) or (max>255) then
801 procedure tenumdef.setmax(_max:longint);
808 procedure tenumdef.setmin(_min:longint);
815 function tenumdef.min:longint;
821 function tenumdef.max:longint;
827 procedure tenumdef.deref;
830 resolvedef(pdef(basedef));
834 destructor tenumdef.done;
840 procedure tenumdef.write;
843 writedefref(basedef);
847 current_ppu^.writeentry(ibenumdef);
851 function tenumdef.getrangecheckstring : string;
853 if (cs_create_smart in aktmoduleswitches) then
854 getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
856 getrangecheckstring:='R_'+tostr(rangenr);
860 procedure tenumdef.genrangecheck;
864 { generate two constant for bounds }
866 if (cs_create_smart in aktmoduleswitches) then
867 datasegment^.concat(new(pai_symbol,initname_global(getrangecheckstring,8)))
869 datasegment^.concat(new(pai_symbol,initname(getrangecheckstring,8)));
870 datasegment^.concat(new(pai_const,init_32bit(min)));
871 datasegment^.concat(new(pai_const,init_32bit(max)));
877 function tenumdef.stabstring : pchar;
883 memsize := memsizeinc;
885 { we can specify the size with @s<size>; prefix PM }
886 if savesize <> target_os.size_of_longint then
887 strpcopy(st,'@s'+tostr(savesize)+';e')
893 s :=p^.name+':'+tostr(p^.value)+',';
894 { place for the ending ';' also }
895 if (strlen(st)+length(s)+1<memsize) then
896 strpcopy(strend(st),s)
899 getmem(st2,memsize+memsizeinc);
903 memsize := memsize+memsizeinc;
904 strpcopy(strend(st),s);
908 strpcopy(strend(st),';');
909 stabstring := strnew(st);
915 procedure tenumdef.write_child_rtti_data;
917 if assigned(basedef) then
918 basedef^.get_rtti_label;
922 procedure tenumdef.write_rtti_data;
928 rttilist^.concat(new(pai_const,init_8bit(tkEnumeration)));
932 rttilist^.concat(new(pai_const,init_8bit(otUByte)));
934 rttilist^.concat(new(pai_const,init_8bit(otUWord)));
936 rttilist^.concat(new(pai_const,init_8bit(otULong)));
938 rttilist^.concat(new(pai_const,init_32bit(min)));
939 rttilist^.concat(new(pai_const,init_32bit(max)));
940 if assigned(basedef) then
941 rttilist^.concat(new(pai_const_symbol,initname(basedef^.get_rtti_label)))
943 rttilist^.concat(new(pai_const,init_32bit(0)));
945 while assigned(hp) do
947 rttilist^.concat(new(pai_const,init_8bit(length(hp^.name))));
948 rttilist^.concat(new(pai_string,init(globals.lower(hp^.name))));
951 rttilist^.concat(new(pai_const,init_8bit(0)));
955 function tenumdef.is_publishable : boolean;
957 is_publishable:=true;
960 function tenumdef.gettypename : string;
963 gettypename:='<enumeration type>';
966 {****************************************************************************
968 ****************************************************************************}
970 constructor torddef.init(t : tbasetype;v,b : longint);
982 constructor torddef.load;
986 typ:=tbasetype(readbyte);
994 procedure torddef.setsize;
998 { generate a unsigned range if high<0 and low>=0 }
999 if (low>=0) and (high<0) then
1004 else if (low>=0) and (high<=255) then
1009 else if (low>=-128) and (high<=127) then
1014 else if (low>=0) and (high<=65536) then
1019 else if (low>=-32768) and (high<=32767) then
1038 bool16bit,uwidechar:
1051 { there are no entrys for range checking }
1055 function torddef.getrangecheckstring : string;
1058 if (cs_create_smart in aktmoduleswitches) then
1059 getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
1061 getrangecheckstring:='R_'+tostr(rangenr);
1064 procedure torddef.genrangecheck;
1066 rangechecksize : longint;
1074 { generate two constant for bounds }
1075 getlabelnr(rangenr);
1076 if (cs_create_smart in aktmoduleswitches) then
1077 datasegment^.concat(new(pai_symbol,initname_global(getrangecheckstring,rangechecksize)))
1079 datasegment^.concat(new(pai_symbol,initname(getrangecheckstring,rangechecksize)));
1082 datasegment^.concat(new(pai_const,init_32bit(low)));
1083 datasegment^.concat(new(pai_const,init_32bit(high)));
1085 { for u32bit we need two bounds }
1088 datasegment^.concat(new(pai_const,init_32bit(low)));
1089 datasegment^.concat(new(pai_const,init_32bit($7fffffff)));
1090 datasegment^.concat(new(pai_const,init_32bit($80000000)));
1091 datasegment^.concat(new(pai_const,init_32bit(high)));
1097 procedure torddef.write;
1100 writebyte(byte(typ));
1103 current_ppu^.writeentry(iborddef);
1108 function torddef.stabstring : pchar;
1111 uvoid : stabstring := strpnew(numberstring+';');
1112 {GDB 4.12 for go32 doesn't like boolean as range for 0 to 1 !!!}
1113 {$ifdef Use_integer_types_for_boolean}
1116 bool32bit : stabstring := strpnew('r'+numberstring+';0;255;');
1117 {$else : not Use_integer_types_for_boolean}
1118 bool8bit : stabstring := strpnew('-21;');
1119 bool16bit : stabstring := strpnew('-22;');
1120 bool32bit : stabstring := strpnew('-23;');
1121 u64bit : stabstring := strpnew('-32;');
1122 s64bit : stabstring := strpnew('-31;');
1123 {$endif not Use_integer_types_for_boolean}
1124 { u32bit : stabstring := strpnew('r'+
1125 s32bitdef^.numberstring+';0;-1;'); }
1127 stabstring := strpnew('r'+s32bitdef^.numberstring+';'+tostr(low)+';'+tostr(high)+';');
1133 procedure torddef.write_rtti_data;
1135 procedure dointeger;
1137 trans : array[uchar..bool8bit] of byte =
1138 (otUByte,otUByte,otUWord,otULong,otSByte,otSWord,otSLong,otUByte);
1141 rttilist^.concat(new(pai_const,init_8bit(byte(trans[typ]))));
1142 rttilist^.concat(new(pai_const,init_32bit(low)));
1143 rttilist^.concat(new(pai_const,init_32bit(high)));
1150 rttilist^.concat(new(pai_const,init_8bit(tkInt64)));
1153 rttilist^.concat(new(pai_const,init_32bit($0)));
1154 rttilist^.concat(new(pai_const,init_32bit($8000)));
1156 rttilist^.concat(new(pai_const,init_32bit($ffff)));
1157 rttilist^.concat(new(pai_const,init_32bit($7fff)));
1161 rttilist^.concat(new(pai_const,init_8bit(tkQWord)));
1164 rttilist^.concat(new(pai_const,init_32bit($0)));
1165 rttilist^.concat(new(pai_const,init_32bit($0)));
1167 rttilist^.concat(new(pai_const,init_32bit($0)));
1168 rttilist^.concat(new(pai_const,init_32bit($8000)));
1172 rttilist^.concat(new(pai_const,init_8bit(tkBool)));
1177 rttilist^.concat(new(pai_const,init_8bit(tkChar)));
1182 rttilist^.concat(new(pai_const,init_8bit(tkWChar)));
1187 rttilist^.concat(new(pai_const,init_8bit(tkInteger)));
1194 function torddef.is_publishable : boolean;
1196 is_publishable:=typ in [uchar..bool8bit];
1199 function torddef.gettypename : string;
1202 names : array[tbasetype] of string[20] = ('<unknown type>',
1203 'untyped','Char','Byte','Word','DWord','ShortInt',
1204 'SmallInt','LongInt','Boolean','WordBool',
1205 'LongBool','QWord','Int64','WideChar');
1208 gettypename:=names[typ];
1211 {****************************************************************************
1213 ****************************************************************************}
1215 constructor tfloatdef.init(t : tfloattype);
1224 constructor tfloatdef.load;
1228 typ:=tfloattype(readbyte);
1233 procedure tfloatdef.setsize;
1236 f16bit : savesize:=2;
1238 s32real : savesize:=4;
1239 s64real : savesize:=8;
1240 s80real : savesize:=extended_size;
1241 s64comp : savesize:=8;
1248 procedure tfloatdef.write;
1251 writebyte(byte(typ));
1252 current_ppu^.writeentry(ibfloatdef);
1257 function tfloatdef.stabstring : pchar;
1261 s64real : stabstring := strpnew('r'+
1262 s32bitdef^.numberstring+';'+tostr(savesize)+';0;');
1263 { for fixed real use longint instead to be able to }
1264 { debug something at least }
1266 stabstring := s32bitdef^.stabstring;
1268 stabstring := strpnew('r'+s32bitdef^.numberstring+';0;'+
1270 { found this solution in stabsread.c from GDB v4.16 }
1271 s64comp : stabstring := strpnew('r'+
1272 s32bitdef^.numberstring+';-'+tostr(savesize)+';0;');
1274 { under dos at least you must give a size of twelve instead of 10 !! }
1275 { this is probably do to the fact that in gcc all is pushed in 4 bytes size }
1276 s80real : stabstring := strpnew('r'+s32bitdef^.numberstring+';12;0;');
1279 internalerror(10005);
1285 procedure tfloatdef.write_rtti_data;
1287 {tfloattype = (s32real,s64real,s80real,s64bit,f16bit,f32bit);}
1288 translate : array[tfloattype] of byte =
1289 (ftSingle,ftDouble,ftExtended,ftComp,ftFixed16,ftFixed32);
1291 rttilist^.concat(new(pai_const,init_8bit(tkFloat)));
1293 rttilist^.concat(new(pai_const,init_8bit(translate[typ])));
1297 function tfloatdef.is_publishable : boolean;
1299 is_publishable:=true;
1302 function tfloatdef.gettypename : string;
1305 names : array[tfloattype] of string[20] = (
1306 'Single','Double','Extended','Comp','Fixed','Fixed16');
1309 gettypename:=names[typ];
1312 {****************************************************************************
1314 ****************************************************************************}
1316 constructor tfiledef.inittext;
1321 typedfiletype.reset;
1326 constructor tfiledef.inituntyped;
1330 filetyp:=ft_untyped;
1331 typedfiletype.reset;
1336 constructor tfiledef.inittyped(const tt : ttype);
1346 constructor tfiledef.inittypeddef(p : pdef);
1351 typedfiletype.setdef(p);
1356 constructor tfiledef.load;
1360 filetyp:=tfiletyp(readbyte);
1361 if filetyp=ft_typed then
1364 typedfiletype.reset;
1369 procedure tfiledef.deref;
1372 if filetyp=ft_typed then
1373 typedfiletype.resolve;
1377 procedure tfiledef.setsize;
1389 procedure tfiledef.write;
1392 writebyte(byte(filetyp));
1393 if filetyp=ft_typed then
1394 typedfiletype.write;
1395 current_ppu^.writeentry(ibfiledef);
1400 function tfiledef.stabstring : pchar;
1402 {$IfDef GDBknowsfiles}
1405 stabstring := strpnew('d'+typedfiletype.def^.numberstring{+';'});
1407 stabstring := strpnew('d'+voiddef^.numberstring{+';'});
1409 stabstring := strpnew('d'+cchardef^.numberstring{+';'});
1413 FileRec = Packed Record
1417 _private : array[1..32] of byte;
1418 UserData : array[1..16] of byte;
1419 name : array[0..255] of char;
1421 { the buffer part is still missing !! (PM) }
1422 { but the string could become too long !! }
1423 stabstring := strpnew('s'+tostr(savesize)+
1424 'HANDLE:'+typeglobalnumber('longint')+',0,32;'+
1425 'MODE:'+typeglobalnumber('longint')+',32,32;'+
1426 'RECSIZE:'+typeglobalnumber('longint')+',64,32;'+
1427 '_PRIVATE:ar'+typeglobalnumber('word')+';1;32;'+typeglobalnumber('byte')
1429 'USERDATA:ar'+typeglobalnumber('word')+';1;16;'+typeglobalnumber('byte')
1431 'NAME:ar'+typeglobalnumber('word')+';0;255;'+typeglobalnumber('char')
1437 procedure tfiledef.concatstabto(asmlist : paasmoutput);
1439 { most file defs are unnamed !!! }
1440 if ((typesym = nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
1441 (is_def_stab_written = not_written) then
1443 if assigned(typedfiletype.def) then forcestabto(asmlist,typedfiletype.def);
1444 inherited concatstabto(asmlist);
1449 function tfiledef.gettypename : string;
1454 gettypename:='File';
1456 gettypename:='File Of '+typedfiletype.def^.typename;
1464 {****************************************************************************
1466 ****************************************************************************}
1468 constructor tpointerdef.init(const tt : ttype);
1471 deftype:=pointerdef;
1474 savesize:=target_os.size_of_pointer;
1478 constructor tpointerdef.initfar(const tt : ttype);
1481 deftype:=pointerdef;
1484 savesize:=target_os.size_of_pointer;
1488 constructor tpointerdef.initdef(p : pdef);
1493 tpointerdef.init(t);
1497 constructor tpointerdef.initfardef(p : pdef);
1502 tpointerdef.initfar(t);
1507 constructor tpointerdef.load;
1510 deftype:=pointerdef;
1512 is_far:=(readbyte<>0);
1513 savesize:=target_os.size_of_pointer;
1517 destructor tpointerdef.done;
1519 if assigned(pointertype.def) and
1520 (pointertype.def^.deftype=forwarddef) then
1522 dispose(pointertype.def,done);
1529 procedure tpointerdef.deref;
1532 pointertype.resolve;
1536 procedure tpointerdef.write;
1540 writebyte(byte(is_far));
1541 current_ppu^.writeentry(ibpointerdef);
1546 function tpointerdef.stabstring : pchar;
1548 stabstring := strpnew('*'+pointertype.def^.numberstring);
1552 procedure tpointerdef.concatstabto(asmlist : paasmoutput);
1554 sym_line_no : longint;
1556 if assigned(pointertype.def) and
1557 (pointertype.def^.deftype=forwarddef) then
1560 if ( (typesym=nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
1561 (is_def_stab_written = not_written) then
1563 is_def_stab_written := being_written;
1564 if assigned(pointertype.def) and
1565 (pointertype.def^.deftype in [recorddef,objectdef]) then
1567 nb:=pointertype.def^.numberstring;
1568 {to avoid infinite recursion in record with next-like fields }
1569 if pointertype.def^.is_def_stab_written = being_written then
1571 if assigned(pointertype.def^.typesym) then
1573 if assigned(typesym) then
1575 st := typesym^.name;
1576 sym_line_no:=typesym^.fileinfo.line;
1583 st := '"'+st+':t'+numberstring+'=*'+nb
1584 +'=xs'+pointertype.def^.typesym^.name+':",'+tostr(N_LSYM)+',0,'+tostr(sym_line_no)+',0';
1585 asmlist^.concat(new(pai_stabs,init(strpnew(st))));
1590 is_def_stab_written := not_written;
1591 inherited concatstabto(asmlist);
1593 is_def_stab_written := written;
1597 if assigned(pointertype.def) then
1598 forcestabto(asmlist,pointertype.def);
1599 is_def_stab_written := not_written;
1600 inherited concatstabto(asmlist);
1606 function tpointerdef.gettypename : string;
1609 gettypename:='^'+pointertype.def^.typename;
1612 {****************************************************************************
1614 ****************************************************************************}
1616 constructor tclassrefdef.init(def : pdef);
1618 inherited initdef(def);
1619 deftype:=classrefdef;
1623 constructor tclassrefdef.load;
1625 { be careful, tclassdefref inherits from tpointerdef }
1627 deftype:=classrefdef;
1630 savesize:=target_os.size_of_pointer;
1634 procedure tclassrefdef.write;
1636 { be careful, tclassdefref inherits from tpointerdef }
1639 current_ppu^.writeentry(ibclassrefdef);
1644 function tclassrefdef.stabstring : pchar;
1646 stabstring:=strpnew(pvmtdef^.numberstring+';');
1650 procedure tclassrefdef.concatstabto(asmlist : paasmoutput);
1652 inherited concatstabto(asmlist);
1656 function tclassrefdef.gettypename : string;
1659 gettypename:='Class Of '+pointertype.def^.typename;
1663 {***************************************************************************
1665 ***************************************************************************}
1667 { For i386 smallsets work,
1668 for m68k there are problems
1669 can be test by compiling with -dusesmallset PM }
1671 {$define usesmallset}
1674 constructor tsetdef.init(s : pdef;high : longint);
1678 elementtype.setdef(s);
1679 {$ifdef usesmallset}
1680 { small sets only working for i386 PM }
1684 {$ifdef testvarsets}
1685 if aktsetalloc=0 THEN { $PACKSET Fixed?}
1687 savesize:=Sizeof(longint)
1688 {$ifdef testvarsets}
1689 else {No, use $PACKSET VALUE for rounding}
1690 savesize:=aktsetalloc*((high+aktsetalloc*8-1) DIV (aktsetalloc*8))
1695 {$endif usesmallset}
1702 {$ifdef testvarsets}
1706 savesize:=4*((high+31) div 32);
1709 {$endif testvarsets}
1710 Message(sym_e_ill_type_decl_set);
1714 constructor tsetdef.load;
1719 settype:=tsettype(readbyte);
1721 normset : savesize:=32;
1722 varset : savesize:=readlong;
1723 smallset : savesize:=Sizeof(longint);
1728 destructor tsetdef.done;
1734 procedure tsetdef.write;
1738 writebyte(byte(settype));
1739 if settype=varset then
1740 writelong(savesize);
1741 current_ppu^.writeentry(ibsetdef);
1746 function tsetdef.stabstring : pchar;
1748 { For small sets write a longint, which can at least be seen
1749 in the current GDB's (PFV)
1750 this is obsolete with GDBPAS !!
1751 and anyhow creates problems with version 4.18!! PM
1752 if settype=smallset then
1753 stabstring := strpnew('r'+s32bitdef^.numberstring+';0;0xffffffff;')
1755 stabstring := strpnew('@s'+tostr(savesize)+';S'+elementtype.def^.numberstring);
1759 procedure tsetdef.concatstabto(asmlist : paasmoutput);
1761 if ( not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
1762 (is_def_stab_written = not_written) then
1764 if assigned(elementtype.def) then
1765 forcestabto(asmlist,elementtype.def);
1766 inherited concatstabto(asmlist);
1772 procedure tsetdef.deref;
1775 elementtype.resolve;
1779 procedure tsetdef.write_rtti_data;
1781 rttilist^.concat(new(pai_const,init_8bit(tkSet)));
1783 rttilist^.concat(new(pai_const,init_8bit(otULong)));
1784 rttilist^.concat(new(pai_const_symbol,initname(elementtype.def^.get_rtti_label)));
1788 procedure tsetdef.write_child_rtti_data;
1790 elementtype.def^.get_rtti_label;
1794 function tsetdef.is_publishable : boolean;
1796 is_publishable:=settype=smallset;
1799 function tsetdef.gettypename : string;
1802 if assigned(elementtype.def) then
1803 gettypename:='Set Of '+elementtype.def^.typename
1805 gettypename:='Empty Set';
1809 {***************************************************************************
1811 ***************************************************************************}
1813 constructor tformaldef.init;
1817 stregdef:=registerdef;
1821 registerdef:=stregdef;
1822 { formaldef must be registered at unit level !! }
1823 if registerdef and assigned(current_module) then
1824 if assigned(current_module^.localsymtable) then
1825 psymtable(current_module^.localsymtable)^.registerdef(@self)
1826 else if assigned(current_module^.globalsymtable) then
1827 psymtable(current_module^.globalsymtable)^.registerdef(@self);
1828 savesize:=target_os.size_of_pointer;
1832 constructor tformaldef.load;
1836 savesize:=target_os.size_of_pointer;
1840 procedure tformaldef.write;
1843 current_ppu^.writeentry(ibformaldef);
1848 function tformaldef.stabstring : pchar;
1850 stabstring := strpnew('formal'+numberstring+';');
1854 procedure tformaldef.concatstabto(asmlist : paasmoutput);
1856 { formaldef can't be stab'ed !}
1860 function tformaldef.gettypename : string;
1866 {***************************************************************************
1868 ***************************************************************************}
1870 constructor tarraydef.init(l,h : longint;rd : pdef);
1876 rangetype.setdef(rd);
1879 IsConstructor:=false;
1880 IsArrayOfConst:=false;
1885 constructor tarraydef.load;
1889 { the addresses are calculated later }
1893 highrange:=readlong;
1894 IsArrayOfConst:=boolean(readbyte);
1896 IsConstructor:=false;
1901 function tarraydef.getrangecheckstring : string;
1903 if (cs_create_smart in aktmoduleswitches) then
1904 getrangecheckstring:='R_'+current_module^.modulename^+tostr(rangenr)
1906 getrangecheckstring:='R_'+tostr(rangenr);
1910 procedure tarraydef.genrangecheck;
1914 { generates the data for range checking }
1915 getlabelnr(rangenr);
1916 if (cs_create_smart in aktmoduleswitches) then
1917 datasegment^.concat(new(pai_symbol,initname_global(getrangecheckstring,8)))
1919 datasegment^.concat(new(pai_symbol,initname(getrangecheckstring,8)));
1920 if lowrange<=highrange then
1922 datasegment^.concat(new(pai_const,init_32bit(lowrange)));
1923 datasegment^.concat(new(pai_const,init_32bit(highrange)));
1925 { for big arrays we need two bounds }
1928 datasegment^.concat(new(pai_const,init_32bit(lowrange)));
1929 datasegment^.concat(new(pai_const,init_32bit($7fffffff)));
1930 datasegment^.concat(new(pai_const,init_32bit($80000000)));
1931 datasegment^.concat(new(pai_const,init_32bit(highrange)));
1937 procedure tarraydef.deref;
1940 elementtype.resolve;
1945 procedure tarraydef.write;
1950 writelong(lowrange);
1951 writelong(highrange);
1952 writebyte(byte(IsArrayOfConst));
1953 current_ppu^.writeentry(ibarraydef);
1958 function tarraydef.stabstring : pchar;
1960 stabstring := strpnew('ar'+rangetype.def^.numberstring+';'
1961 +tostr(lowrange)+';'+tostr(highrange)+';'+elementtype.def^.numberstring);
1965 procedure tarraydef.concatstabto(asmlist : paasmoutput);
1967 if (not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
1968 and (is_def_stab_written = not_written) then
1970 {when array are inserted they have no definition yet !!}
1971 if assigned(elementtype.def) then
1972 inherited concatstabto(asmlist);
1978 function tarraydef.elesize : longint;
1980 if isconstructor or is_open_array(@self) then
1982 { strings are stored by address only }
1983 case elementtype.def^.deftype of
1987 elesize:=elementtype.def^.size;
1991 elesize:=elementtype.def^.size;
1995 function tarraydef.size : longint;
1997 {Tarraydef.size may never be called for an open array!}
1998 if highrange<lowrange then
1999 internalerror(99080501);
2002 (highrange-lowrange = $7fffffff) or
2003 { () are needed around elesize-1 to avoid a possible
2004 integer overflow for elesize=1 !! PM }
2005 (($7fffffff div elesize + (elesize -1)) < (highrange - lowrange))
2008 Message(sym_e_segment_too_large);
2011 Else size:=(highrange-lowrange+1)*elesize;
2015 function tarraydef.alignment : longint;
2017 { alignment is the size of the elements }
2018 if elementtype.def^.deftype=recorddef then
2019 alignment:=elementtype.def^.alignment
2025 function tarraydef.needs_inittable : boolean;
2027 needs_inittable:=elementtype.def^.needs_inittable;
2031 procedure tarraydef.write_child_rtti_data;
2033 elementtype.def^.get_rtti_label;
2037 procedure tarraydef.write_rtti_data;
2039 rttilist^.concat(new(pai_const,init_8bit(tkarray)));
2041 { size of elements }
2042 rttilist^.concat(new(pai_const,init_32bit(elesize)));
2043 { count of elements }
2044 rttilist^.concat(new(pai_const,init_32bit(highrange-lowrange+1)));
2046 rttilist^.concat(new(pai_const_symbol,initname(elementtype.def^.get_rtti_label)));
2049 function tarraydef.gettypename : string;
2052 if isarrayofconst or isConstructor then
2054 if isvariant or ((highrange=-1) and (lowrange=0)) then
2055 gettypename:='Array Of Const'
2057 gettypename:='Array Of '+elementtype.def^.typename;
2059 else if is_open_array(@self) then
2060 gettypename:='Array Of '+elementtype.def^.typename
2063 if rangetype.def^.deftype=enumdef then
2064 gettypename:='Array['+rangetype.def^.typename+'] Of '+elementtype.def^.typename
2066 gettypename:='Array['+tostr(lowrange)+'..'+
2067 tostr(highrange)+'] Of '+elementtype.def^.typename
2071 {***************************************************************************
2073 ***************************************************************************}
2075 constructor trecorddef.init(p : psymtable);
2080 symtable^.defowner := @self;
2081 symtable^.dataalignment:=packrecordalignment[aktpackrecords];
2085 constructor trecorddef.load;
2087 oldread_member : boolean;
2092 oldread_member:=read_member;
2094 symtable:=new(psymtable,loadas(recordsymtable));
2095 read_member:=oldread_member;
2096 symtable^.defowner := @self;
2100 destructor trecorddef.done;
2102 if assigned(symtable) then
2103 dispose(symtable,done);
2109 binittable : boolean;
2111 procedure check_rec_inittable(s : pnamedindexobject);
2114 if (not binittable) and
2115 (psym(s)^.typ=varsym) and
2116 assigned(pvarsym(s)^.vartype.def) then
2118 if ((pvarsym(s)^.vartype.def^.deftype<>objectdef) or
2119 not(pobjectdef(pvarsym(s)^.vartype.def)^.is_class)) then
2120 binittable:=pvarsym(s)^.vartype.def^.needs_inittable;
2125 function trecorddef.needs_inittable : boolean;
2129 { there are recursive calls to needs_rtti possible, }
2130 { so we have to change to old value how else should }
2131 { we do that ? check_rec_rtti can't be a nested }
2132 { procedure of needs_rtti ! }
2135 symtable^.foreach({$ifndef TP}@{$endif}check_rec_inittable);
2136 needs_inittable:=binittable;
2141 procedure trecorddef.deref;
2143 oldrecsyms : psymtable;
2146 oldrecsyms:=aktrecordsymtable;
2147 aktrecordsymtable:=symtable;
2148 { now dereference the definitions }
2150 aktrecordsymtable:=oldrecsyms;
2154 procedure trecorddef.write;
2156 oldread_member : boolean;
2158 oldread_member:=read_member;
2161 writelong(savesize);
2162 current_ppu^.writeentry(ibrecorddef);
2163 self.symtable^.writeas;
2164 read_member:=oldread_member;
2167 function trecorddef.size:longint;
2169 size:=symtable^.datasize;
2173 function trecorddef.alignment:longint;
2178 { also check the first symbol for it's size, because a
2179 packed record has dataalignment of 1, but the first
2180 sym could be a longint which should be aligned on 4 bytes,
2181 this is compatible with C record packing (PFV) }
2182 hp:=pvarsym(symtable^.symindex^.first);
2183 if assigned(hp) then
2185 l:=hp^.vartype.def^.size;
2186 if l>symtable^.dataalignment then
2197 alignment:=symtable^.dataalignment;
2200 alignment:=symtable^.dataalignment;
2204 Const StabRecString : pchar = Nil;
2205 StabRecSize : longint = 0;
2206 RecOffset : Longint = 0;
2208 procedure addname(p : pnamedindexobject);
2210 news, newrec : pchar;
2214 { static variables from objects are like global objects }
2215 if (sp_static in psym(p)^.symoptions) then
2217 If psym(p)^.typ = varsym then
2219 if (sp_protected in psym(p)^.symoptions) then
2221 else if (sp_private in psym(p)^.symoptions) then
2225 if not assigned(pvarsym(p)^.vartype.def) then
2226 writeln(pvarsym(p)^.name);
2227 { class fields are pointers PM, obsolete now PM }
2228 {if (pvarsym(p)^.vartype.def^.deftype=objectdef) and
2229 pobjectdef(pvarsym(p)^.vartype.def)^.is_class then
2231 size:=pvarsym(p)^.vartype.def^.size;
2232 { open arrays made overflows !! }
2233 if size>$fffffff then
2235 newrec := strpnew(p^.name+':'+spec+pvarsym(p)^.vartype.def^.numberstring
2236 +','+tostr(pvarsym(p)^.address*8)+','
2237 +tostr(size*8)+';');
2238 if strlen(StabRecString) + strlen(newrec) >= StabRecSize-256 then
2240 getmem(news,stabrecsize+memsizeinc);
2241 strcopy(news,stabrecstring);
2242 freemem(stabrecstring,stabrecsize);
2243 stabrecsize:=stabrecsize+memsizeinc;
2244 stabrecstring:=news;
2246 strcat(StabRecstring,newrec);
2248 {This should be used for case !!}
2249 RecOffset := RecOffset + pvarsym(p)^.vartype.def^.size;
2254 function trecorddef.stabstring : pchar;
2256 oldsize,oldrecoffset : longint;
2258 oldrec := stabrecstring;
2259 oldsize:=stabrecsize;
2260 GetMem(stabrecstring,memsizeinc);
2261 stabrecsize:=memsizeinc;
2262 strpcopy(stabRecString,'s'+tostr(size));
2263 OldRecOffset:=RecOffset;
2265 symtable^.foreach({$ifndef TP}@{$endif}addname);
2266 { FPC doesn't want to convert a char to a pchar}
2268 strpcopy(strend(StabRecString),';');
2269 stabstring := strnew(StabRecString);
2270 Freemem(stabrecstring,stabrecsize);
2271 stabrecstring := oldrec;
2272 stabrecsize:=oldsize;
2273 RecOffset:=OldRecOffset;
2277 procedure trecorddef.concatstabto(asmlist : paasmoutput);
2279 if (not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
2280 (is_def_stab_written = not_written) then
2281 inherited concatstabto(asmlist);
2289 procedure count_inittable_fields(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
2291 if ((psym(sym)^.typ=varsym) and
2292 pvarsym(sym)^.vartype.def^.needs_inittable)
2293 and ((pvarsym(sym)^.vartype.def^.deftype<>objectdef) or
2294 (not pobjectdef(pvarsym(sym)^.vartype.def)^.is_class)) then
2299 procedure count_fields(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
2305 procedure write_field_inittable(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
2307 if ((psym(sym)^.typ=varsym) and
2308 pvarsym(sym)^.vartype.def^.needs_inittable) and
2309 ((pvarsym(sym)^.vartype.def^.deftype<>objectdef) or
2310 (not pobjectdef(pvarsym(sym)^.vartype.def)^.is_class)) then
2312 rttilist^.concat(new(pai_const_symbol,init(pvarsym(sym)^.vartype.def^.get_inittable_label)));
2313 rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
2318 procedure write_field_rtti(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
2320 rttilist^.concat(new(pai_const_symbol,initname(pvarsym(sym)^.vartype.def^.get_rtti_label)));
2321 rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
2325 procedure generate_child_inittable(sym:pnamedindexobject);{$ifndef fpc}far;{$endif}
2327 if (psym(sym)^.typ=varsym) and
2328 pvarsym(sym)^.vartype.def^.needs_inittable then
2329 { force inittable generation }
2330 pvarsym(sym)^.vartype.def^.get_inittable_label;
2334 procedure generate_child_rtti(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
2336 pvarsym(sym)^.vartype.def^.get_rtti_label;
2340 procedure trecorddef.write_child_rtti_data;
2342 symtable^.foreach({$ifndef TP}@{$endif}generate_child_rtti);
2346 procedure trecorddef.write_child_init_data;
2348 symtable^.foreach({$ifndef TP}@{$endif}generate_child_inittable);
2352 procedure trecorddef.write_rtti_data;
2354 rttilist^.concat(new(pai_const,init_8bit(tkrecord)));
2356 rttilist^.concat(new(pai_const,init_32bit(size)));
2358 symtable^.foreach({$ifndef TP}@{$endif}count_fields);
2359 rttilist^.concat(new(pai_const,init_32bit(count)));
2360 symtable^.foreach({$ifndef TP}@{$endif}write_field_rtti);
2364 procedure trecorddef.write_init_data;
2366 rttilist^.concat(new(pai_const,init_8bit(tkrecord)));
2368 rttilist^.concat(new(pai_const,init_32bit(size)));
2370 symtable^.foreach({$ifndef TP}@{$endif}count_inittable_fields);
2371 rttilist^.concat(new(pai_const,init_32bit(count)));
2372 symtable^.foreach({$ifndef TP}@{$endif}write_field_inittable);
2375 function trecorddef.gettypename : string;
2378 gettypename:='<record type>'
2382 {***************************************************************************
2384 ***************************************************************************}
2386 constructor tabstractprocdef.init;
2391 proctypeoption:=potype_none;
2392 proccalloptions:=[];
2394 rettype.setdef(voiddef);
2396 savesize:=target_os.size_of_pointer;
2400 destructor tabstractprocdef.done;
2407 procedure tabstractprocdef.concatpara(tt:ttype;vsp : tvarspez);
2419 { all functions returning in FPU are
2420 assume to use 2 FPU registers
2421 until the function implementation
2423 procedure tabstractprocdef.test_if_fpu_result;
2425 if assigned(rettype.def) and is_fpu(rettype.def) then
2430 procedure tabstractprocdef.deref;
2436 hp:=pparaitem(para^.first);
2437 while assigned(hp) do
2439 hp^.paratype.resolve;
2440 hp:=pparaitem(hp^.next);
2445 constructor tabstractprocdef.load;
2454 proctypeoption:=tproctypeoption(readlong);
2455 readsmallset(proccalloptions);
2456 readsmallset(procoptions);
2458 savesize:=target_os.size_of_pointer;
2459 for i:=1 to count do
2462 hp^.paratyp:=tvarspez(readbyte);
2463 { hp^.register:=tregister(readbyte); }
2471 procedure tabstractprocdef.write;
2477 current_ppu^.do_interface_crc:=false;
2478 writebyte(fpu_used);
2479 writelong(ord(proctypeoption));
2480 writesmallset(proccalloptions);
2481 writesmallset(procoptions);
2482 writeword(para^.count);
2483 hp:=pparaitem(para^.first);
2484 while assigned(hp) do
2486 writebyte(byte(hp^.paratyp));
2487 { writebyte(byte(hp^.register)); }
2489 hp:=pparaitem(hp^.next);
2494 function tabstractprocdef.para_size(alignsize:longint) : longint;
2500 pdc:=pparaitem(para^.first);
2501 while assigned(pdc) do
2503 case pdc^.paratyp of
2504 vs_var : inc(l,target_os.size_of_pointer);
2506 vs_const : if push_addr_param(pdc^.paratype.def) then
2507 inc(l,target_os.size_of_pointer)
2509 inc(l,pdc^.paratype.def^.size);
2511 l:=align(l,alignsize);
2512 pdc:=pparaitem(pdc^.next);
2518 function tabstractprocdef.demangled_paras : string;
2524 hp:=pparaitem(para^.last);
2525 while assigned(hp) do
2527 if assigned(hp^.paratype.def^.typesym) then
2528 s:=s+hp^.paratype.def^.typesym^.name
2529 else if hp^.paratyp=vs_var then
2531 else if hp^.paratyp=vs_const then
2533 hp:=pparaitem(hp^.previous);
2534 if assigned(hp) then
2542 function tabstractprocdef.proccalloption2str : string;
2545 mask : tproccalloption;
2550 proccallopt : array[1..proccallopts] of tproccallopt=(
2551 (mask:pocall_none; str:''),
2552 (mask:pocall_clearstack; str:'ClearStack'),
2553 (mask:pocall_leftright; str:'LeftRight'),
2554 (mask:pocall_cdecl; str:'Cdecl'),
2555 (mask:pocall_register; str:'Register'),
2556 (mask:pocall_stdcall; str:'StdCall'),
2557 (mask:pocall_safecall; str:'SafeCall'),
2558 (mask:pocall_palmossyscall;str:'PalmOSSysCall'),
2559 (mask:pocall_system; str:'System'),
2560 (mask:pocall_inline; str:'Inline'),
2561 (mask:pocall_internproc; str:'InternProc'),
2562 (mask:pocall_internconst; str:'InternConst')
2571 for i:=1to proccallopts do
2572 if (proccallopt[i].mask in proccalloptions) then
2578 s:=s+proccallopt[i].str;
2580 proccalloption2str:=s;
2585 function tabstractprocdef.stabstring : pchar;
2587 stabstring := strpnew('abstractproc'+numberstring+';');
2591 procedure tabstractprocdef.concatstabto(asmlist : paasmoutput);
2593 if (not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
2594 and (is_def_stab_written = not_written) then
2596 if assigned(rettype.def) then forcestabto(asmlist,rettype.def);
2597 inherited concatstabto(asmlist);
2603 {***************************************************************************
2605 ***************************************************************************}
2607 constructor tprocdef.init;
2612 nextoverloaded:=nil;
2613 fileinfo:=aktfilepos;
2615 localst:=new(psymtable,init(localsymtable));
2616 parast:=new(psymtable,init(parasymtable));
2617 localst^.defowner:=@self;
2618 parast^.defowner:=@self;
2619 { this is used by insert
2620 to check same names in parast and localst }
2621 localst^.next:=parast;
2626 if (cs_browser in aktmoduleswitches) and make_ref then
2628 defref:=new(pref,init(defref,@tokenpos));
2632 { first, we assume that all registers are used }
2634 usedregisters:=[firstreg..lastreg];
2640 usedregisters:=$FFFF;
2644 interfacedef:=false;
2653 constructor tprocdef.load;
2661 readnormalset(usedregisters);
2664 usedregisters:=readbyte;
2667 usedregisters:=readword;
2671 setstring(_mangledname,s);
2673 extnumber:=readlong;
2674 nextoverloaded:=pprocdef(readdefref);
2675 _class := pobjectdef(readdefref);
2676 readposinfo(fileinfo);
2678 if (cs_link_deffile in aktglobalswitches) and
2679 (tf_need_export in target_info.flags) and
2680 (po_exports in procoptions) then
2681 deffile.AddExport(mangledname);
2686 interfacedef:=false;
2697 Const local_symtable_index : longint = $8001;
2699 procedure tprocdef.load_references;
2702 {$ifndef NOLOCALBROWSER}
2705 {$endif ndef NOLOCALBROWSER}
2706 move_last : boolean;
2708 move_last:=lastwritten=lastref;
2709 while (not current_ppu^.endofentry) do
2713 lastref:=new(pref,init(lastref,@pos));
2714 lastref^.is_written:=true;
2719 lastwritten:=lastref;
2720 if ((current_module^.flags and uf_local_browser)<>0)
2721 and is_in_current then
2723 {$ifndef NOLOCALBROWSER}
2724 oldsymtablestack:=symtablestack;
2725 st:=aktlocalsymtable;
2726 new(parast,loadas(parasymtable));
2727 parast^.defowner:=@self;
2728 aktlocalsymtable:=parast;
2730 parast^.next:=owner;
2731 parast^.load_browser;
2732 aktlocalsymtable:=st;
2733 new(localst,loadas(localsymtable));
2734 localst^.defowner:=@self;
2735 aktlocalsymtable:=localst;
2736 symtablestack:=parast;
2738 localst^.next:=parast;
2739 localst^.load_browser;
2740 aktlocalsymtable:=st;
2741 symtablestack:=oldsymtablestack;
2742 {$endif ndef NOLOCALBROWSER}
2747 function tprocdef.write_references : boolean;
2750 {$ifndef NOLOCALBROWSER}
2753 {$endif ndef NOLOCALBROWSER}
2754 move_last : boolean;
2756 move_last:=lastwritten=lastref;
2757 if move_last and (((current_module^.flags and uf_local_browser)=0)
2758 or not is_in_current) then
2760 { write address of this symbol }
2763 if assigned(lastwritten) then
2767 while assigned(ref) do
2769 if ref^.moduleindex=current_module^.unit_index then
2771 writeposinfo(ref^.posinfo);
2772 ref^.is_written:=true;
2776 else if not ref^.is_written then
2778 else if move_last then
2782 current_ppu^.writeentry(ibdefref);
2783 write_references:=true;
2784 if ((current_module^.flags and uf_local_browser)<>0)
2785 and is_in_current then
2787 {$ifndef NOLOCALBROWSER}
2789 if (owner^.symtabletype<>localsymtable) then
2790 while assigned(pdo) do
2792 if pdo^.symtable<>aktrecordsymtable then
2794 pdo^.symtable^.unitid:=local_symtable_index;
2795 inc(local_symtable_index);
2800 { we need TESTLOCALBROWSER para and local symtables
2801 PPU files are then easier to read PM }
2802 if not assigned(parast) then
2803 parast:=new(psymtable,init(parasymtable));
2804 parast^.defowner:=@self;
2805 st:=aktlocalsymtable;
2806 aktlocalsymtable:=parast;
2808 parast^.unitid:=local_symtable_index;
2809 inc(local_symtable_index);
2810 parast^.write_browser;
2811 if not assigned(localst) then
2812 localst:=new(psymtable,init(localsymtable));
2813 localst^.defowner:=@self;
2814 aktlocalsymtable:=localst;
2816 localst^.unitid:=local_symtable_index;
2817 inc(local_symtable_index);
2818 localst^.write_browser;
2819 aktlocalsymtable:=st;
2821 local_symtable_index:=local_symtable_index-2;
2823 if (owner^.symtabletype<>localsymtable) then
2824 while assigned(pdo) do
2826 if pdo^.symtable<>aktrecordsymtable then
2827 dec(local_symtable_index);
2830 {$endif ndef NOLOCALBROWSER}
2836 procedure tprocdef.add_to_browserlog;
2838 if assigned(defref) then
2840 browserlog.AddLog('***'+mangledname);
2841 browserlog.AddLogRefs(defref);
2842 if (current_module^.flags and uf_local_browser)<>0 then
2844 if assigned(parast) then
2845 parast^.writebrowserlog;
2846 if assigned(localst) then
2847 localst^.writebrowserlog;
2854 destructor tprocdef.done;
2856 if assigned(defref) then
2859 dispose(defref,done);
2861 if assigned(parast) then
2862 dispose(parast,done);
2863 if assigned(localst) and (localst^.symtabletype<>staticsymtable) then
2864 dispose(localst,done);
2865 if (pocall_inline in proccalloptions) and assigned(code) then
2866 disposetree(ptree(code));
2867 if (po_msgstr in procoptions) then
2868 strdispose(messageinf.str);
2873 assigned(_mangledname) then
2874 strdispose(_mangledname);
2879 procedure tprocdef.write;
2882 current_ppu^.do_interface_crc:=false;
2883 { set all registers to used for simplified compilation PM }
2884 if simplify_ppu then
2887 usedregisters:=[firstreg..lastreg];
2893 usedregisters:=$ffff;
2899 writenormalset(usedregisters);
2902 writebyte(usedregisters);
2905 writeword(usedregisters);
2908 current_ppu^.do_interface_crc:=true;
2909 writestring(mangledname);
2910 writelong(extnumber);
2911 if (proctypeoption<>potype_operator) then
2912 writedefref(nextoverloaded)
2915 { only write the overloads from the same unit }
2916 if assigned(nextoverloaded) and
2917 (nextoverloaded^.owner=owner) then
2918 writedefref(nextoverloaded)
2922 writedefref(_class);
2923 writeposinfo(fileinfo);
2924 if (pocall_inline in proccalloptions) then
2927 - the para and the local symtable
2928 - the code ptree !! PM
2929 writesymtable(parast);
2930 writesymtable(localst);
2931 writeptree(ptree(code));
2934 current_ppu^.writeentry(ibprocdef);
2938 function tprocdef.haspara:boolean;
2940 haspara:=assigned(aktprocsym^.definition^.parast^.symindex^.first);
2945 procedure addparaname(p : psym);
2948 if pvarsym(p)^.varspez = vs_value then vs := '1'
2950 strpcopy(strend(StabRecString),p^.name+':'+pvarsym(p)^.vartype.def^.numberstring+','+vs+';');
2954 function tprocdef.stabstring : pchar;
2959 oldrec := stabrecstring;
2960 getmem(StabRecString,1024);
2961 strpcopy(StabRecString,'f'+rettype.def^.numberstring);
2965 strpcopy(strend(StabRecString),','+tostr(i)+';');
2966 (* confuse gdb !! PM
2967 if assigned(parast) then
2968 parast^.foreach({$ifndef TP}@{$endif}addparaname)
2973 while assigned(param) do
2976 if param^.paratyp = vs_value then vartyp := '1' else vartyp := '0';
2977 {Here we have lost the parameter names !!}
2978 {using lower case parameters }
2979 strpcopy(strend(stabrecstring),'p'+tostr(i)
2980 +':'+param^.paratype.def^.numberstring+','+vartyp+';');
2981 param := param^.next;
2984 {strpcopy(strend(StabRecString),';');}
2986 stabstring := strnew(stabrecstring);
2987 freemem(stabrecstring,1024);
2988 stabrecstring := oldrec;
2992 procedure tprocdef.concatstabto(asmlist : paasmoutput);
2998 procedure tprocdef.deref;
3001 resolvedef(pdef(nextoverloaded));
3002 resolvedef(pdef(_class));
3006 function tprocdef.mangledname : string;
3018 symbolstream.seek(longint(_mangledname));
3019 symbolstream.read(b,1);
3020 symbolstream.read(s[1],b);
3027 mangledname:=strpas(_mangledname);
3033 function tprocdef.procname: string;
3039 { delete leading $$'s }
3046 { delete leading _$'s }
3057 procname:=Copy(s,1,l-1);
3061 function tprocdef.cplusplusmangledname : string;
3067 if _class <> nil then
3069 s2 := _class^.objname^;
3070 s := s+'__'+tostr(length(s2))+s2;
3071 end else s := s + '_';
3072 param := pparaitem(para^.first);
3073 while assigned(param) do
3075 s2 := param^.paratype.def^.typesym^.name;
3076 s := s+tostr(length(s2))+s2;
3077 param := pparaitem(param^.next);
3079 cplusplusmangledname:=s;
3084 procedure tprocdef.setmangledname(const s : string);
3086 if {$ifdef tp}not(use_big) and{$endif} (assigned(_mangledname)) then
3089 dec(manglenamesize,length(_mangledname^));
3091 strdispose(_mangledname);
3093 setstring(_mangledname,s);
3095 inc(manglenamesize,length(s));
3098 if assigned(parast) then
3100 stringdispose(parast^.name);
3101 parast^.name:=stringdup('args of '+s);
3103 if assigned(localst) then
3105 stringdispose(localst^.name);
3106 localst^.name:=stringdup('locals of '+s);
3112 {***************************************************************************
3114 ***************************************************************************}
3116 constructor tprocvardef.init;
3119 deftype:=procvardef;
3123 constructor tprocvardef.load;
3126 deftype:=procvardef;
3130 procedure tprocvardef.write;
3132 { here we cannot get a real good value so just give something }
3134 { a more secure way would be
3135 to allways store in a temp }
3136 if is_fpu(rettype.def) then
3141 current_ppu^.writeentry(ibprocvardef);
3145 function tprocvardef.size : longint;
3147 if (po_methodpointer in procoptions) then
3148 size:=2*target_os.size_of_pointer
3150 size:=target_os.size_of_pointer;
3155 function tprocvardef.stabstring : pchar;
3160 { i := para^.count; }
3162 { it is not a function but a function pointer !! (PM) }
3164 strpcopy(nss,'*f'+rettype.def^.numberstring{+','+tostr(i)}+';');
3165 { this confuses gdb !!
3166 we should use 'F' instead of 'f' but
3167 as we use c++ language mode
3168 it does not like that either
3169 Please do not remove this part
3171 gdb for pascal is ready PM }
3175 while assigned(param) do
3178 if param^.paratyp = vs_value then vartyp := '1' else vartyp := '0';
3179 {Here we have lost the parameter names !!}
3180 pst := strpnew('p'+tostr(i)+':'+param^.paratype.def^.numberstring+','+vartyp+';');
3183 param := param^.next;
3185 {strpcopy(strend(nss),';');}
3186 stabstring := strnew(nss);
3191 procedure tprocvardef.concatstabto(asmlist : paasmoutput);
3193 if ( not assigned(typesym) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches))
3194 and (is_def_stab_written = not_written) then
3195 inherited concatstabto(asmlist);
3196 is_def_stab_written:=written;
3201 procedure tprocvardef.write_rtti_data;
3204 methodkind, paraspec : byte;
3206 if po_methodpointer in procoptions then
3208 { write method id and name }
3209 rttilist^.concat(new(pai_const,init_8bit(tkmethod)));
3212 { write kind of method (can only be function or procedure)}
3213 if rettype.def = pdef(voiddef) then { ### typecast shoudln't be necessary! (sg) }
3214 methodkind := mkProcedure
3216 methodkind := mkFunction;
3217 rttilist^.concat(new(pai_const,init_8bit(methodkind)));
3219 { get # of parameters }
3220 rttilist^.concat(new(pai_const,init_8bit(para^.count)));
3222 { write parameter info. The parameters must be written in reverse order
3223 if this method uses right to left parameter pushing! }
3224 if (pocall_leftright in proccalloptions) then
3225 pdc:=pparaitem(para^.last)
3227 pdc:=pparaitem(para^.first);
3228 while assigned(pdc) do
3230 case pdc^.paratyp of
3231 vs_value: paraspec := 0;
3232 vs_const: paraspec := pfConst;
3233 vs_var : paraspec := pfVar;
3235 { write flags for current parameter }
3236 rttilist^.concat(new(pai_const,init_8bit(paraspec)));
3237 { write name of current parameter ### how can I get this??? (sg)}
3238 rttilist^.concat(new(pai_const,init_8bit(0)));
3240 { write name of type of current parameter }
3241 pdc^.paratype.def^.write_rtti_name;
3243 if (pocall_leftright in proccalloptions) then
3244 pdc:=pparaitem(pdc^.previous)
3246 pdc:=pparaitem(pdc^.next);
3249 { write name of result type }
3250 rettype.def^.write_rtti_name;
3255 procedure tprocvardef.write_child_rtti_data;
3261 function tprocvardef.is_publishable : boolean;
3263 is_publishable:=(po_methodpointer in procoptions);
3267 function tprocvardef.gettypename : string;
3269 if assigned(rettype.def) and
3270 (rettype.def<>pdef(voiddef)) then
3271 gettypename:='<procedure variable type of function'+demangled_paras+
3272 ':'+rettype.def^.gettypename+';'+proccalloption2str+'>'
3274 gettypename:='<procedure variable type of procedure'+demangled_paras+
3275 ';'+proccalloption2str+'>';
3279 {***************************************************************************
3281 ***************************************************************************}
3285 vtabletype : word = 0;
3286 vtableassigned : boolean = false;
3289 constructor tobjectdef.init(const n : string;c : pobjectdef);
3295 symtable:=new(psymtable,init(objectsymtable));
3296 symtable^.name := stringdup(n);
3297 { create space for vmt !! }
3299 symtable^.datasize:=0;
3300 symtable^.defowner:=@self;
3301 symtable^.dataalignment:=packrecordalignment[aktpackrecords];
3303 objname:=stringdup(n);
3305 writing_class_record_stab:=false;
3310 constructor tobjectdef.load;
3312 oldread_member : boolean;
3317 vmt_offset:=readlong;
3318 objname:=stringdup(readstring);
3319 childof:=pobjectdef(readdefref);
3320 readsmallset(objectoptions);
3321 has_rtti:=boolean(readbyte);
3323 oldread_member:=read_member;
3325 symtable:=new(psymtable,loadas(objectsymtable));
3326 read_member:=oldread_member;
3328 symtable^.defowner:=@self;
3329 symtable^.name := stringdup(objname^);
3331 { handles the predefined class tobject }
3332 { the last TOBJECT which is loaded gets }
3334 if (childof=nil) and
3336 (objname^='TOBJECT') then
3337 class_tobject:=@self;
3339 writing_class_record_stab:=false;
3344 destructor tobjectdef.done;
3346 if assigned(symtable) then
3347 dispose(symtable,done);
3348 if (oo_is_forward in objectoptions) then
3349 Message1(sym_e_class_forward_not_resolved,objname^);
3350 stringdispose(objname);
3355 procedure tobjectdef.write;
3357 oldread_member : boolean;
3361 writelong(vmt_offset);
3362 writestring(objname^);
3363 writedefref(childof);
3364 writesmallset(objectoptions);
3365 writebyte(byte(has_rtti));
3366 current_ppu^.writeentry(ibobjectdef);
3368 oldread_member:=read_member;
3371 read_member:=oldread_member;
3375 procedure tobjectdef.deref;
3377 oldrecsyms : psymtable;
3380 resolvedef(pdef(childof));
3381 oldrecsyms:=aktrecordsymtable;
3382 aktrecordsymtable:=symtable;
3384 aktrecordsymtable:=oldrecsyms;
3388 procedure tobjectdef.set_parent( c : pobjectdef);
3390 { nothing to do if the parent was not forward !}
3391 if assigned(childof) then
3394 { some options are inherited !! }
3397 objectoptions:=objectoptions+(c^.objectoptions*
3398 [oo_has_virtual,oo_has_private,oo_has_protected,oo_has_constructor,oo_has_destructor]);
3399 { add the data of the anchestor class }
3400 inc(symtable^.datasize,c^.symtable^.datasize);
3401 if (oo_has_vmt in objectoptions) and
3402 (oo_has_vmt in c^.objectoptions) then
3403 dec(symtable^.datasize,target_os.size_of_pointer);
3404 { if parent has a vmt field then
3405 the offset is the same for the child PM }
3406 if (oo_has_vmt in c^.objectoptions) or is_class then
3408 vmt_offset:=c^.vmt_offset;
3410 include(objectoptions,oo_has_vmt);
3412 objectoptions:=objectoptions+[oo_has_vmt];
3416 savesize := symtable^.datasize;
3420 procedure tobjectdef.insertvmt;
3422 if (oo_has_vmt in objectoptions) then
3423 internalerror(12345)
3426 { first round up to multiple of 4 }
3427 if (symtable^.dataalignment=2) then
3429 if (symtable^.datasize and 1)<>0 then
3430 inc(symtable^.datasize);
3433 if (symtable^.dataalignment>=4) then
3435 if (symtable^.datasize mod 4) <> 0 then
3436 inc(symtable^.datasize,4-(symtable^.datasize mod 4));
3438 vmt_offset:=symtable^.datasize;
3439 inc(symtable^.datasize,target_os.size_of_pointer);
3440 include(objectoptions,oo_has_vmt);
3445 procedure tobjectdef.check_forwards;
3447 symtable^.check_forwards;
3448 if (oo_is_forward in objectoptions) then
3450 { ok, in future, the forward can be resolved }
3451 Message1(sym_e_class_forward_not_resolved,objname^);
3453 exclude(objectoptions,oo_is_forward);
3455 objectoptions:=objectoptions-[oo_is_forward];
3461 { true, if self inherits from d (or if they are equal) }
3462 function tobjectdef.is_related(d : pobjectdef) : boolean;
3467 while assigned(hp) do
3482 procedure _searchdestructor(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
3488 { if we found already a destructor, then we exit }
3489 if assigned(sd) then
3491 if psym(sym)^.typ=procsym then
3493 p:=pprocsym(sym)^.definition;
3494 while assigned(p) do
3496 if p^.proctypeoption=potype_destructor then
3501 p:=p^.nextoverloaded;
3506 function tobjectdef.searchdestructor : pprocdef;
3512 searchdestructor:=nil;
3515 while assigned(o) do
3517 symtable^.foreach({$ifndef TP}@{$endif}_searchdestructor);
3518 if assigned(sd) then
3520 searchdestructor:=sd;
3527 function tobjectdef.size : longint;
3529 if (oo_is_class in objectoptions) then
3530 size:=target_os.size_of_pointer
3532 size:=symtable^.datasize;
3536 function tobjectdef.alignment:longint;
3538 alignment:=symtable^.dataalignment;
3542 function tobjectdef.vmtmethodoffset(index:longint):longint;
3544 { for offset of methods for classes, see rtl/inc/objpash.inc }
3546 vmtmethodoffset:=(index+12)*target_os.size_of_pointer
3549 vmtmethodoffset:=(index+4)*target_os.size_of_pointer;
3551 vmtmethodoffset:=(index+3)*target_os.size_of_pointer;
3556 function tobjectdef.vmt_mangledname : string;
3557 {DM: I get a nil pointer on the owner name. I don't know if this
3558 mayhappen, and I have therefore fixed the problem by doing nil pointer
3563 if not(oo_has_vmt in objectoptions) then
3564 Message1(parser_object_has_no_vmt,objname^);
3565 if owner^.name=nil then
3573 vmt_mangledname:='VMT_'+s1+'$_'+s2;
3577 function tobjectdef.rtti_name : string;
3581 if owner^.name=nil then
3589 rtti_name:='RTTI_'+s1+'$_'+s2;
3593 function tobjectdef.is_class : boolean;
3595 is_class:=(oo_is_class in objectoptions);
3600 procedure addprocname(p :pnamedindexobject);
3601 var virtualind,argnames : string;
3602 news, newrec : pchar;
3610 If psym(p)^.typ = procsym then
3612 pd := pprocsym(p)^.definition;
3613 { this will be used for full implementation of object stabs
3616 while assigned(ipd^.nextoverloaded) do ipd := ipd^.nextoverloaded;
3617 if (po_virtualmethod in pd^.procoptions) then
3619 lindex := pd^.extnumber;
3620 {doesnt seem to be necessary
3621 lindex := lindex or $80000000;}
3622 virtualind := '*'+tostr(lindex)+';'+ipd^._class^.classnumberstring+';'
3627 { used by gdbpas to recognize constructor and destructors }
3628 if (pd^.proctypeoption=potype_constructor) then
3630 else if (pd^.proctypeoption=potype_destructor) then
3635 { arguments are not listed here }
3636 {we don't need another definition}
3637 para := pparaitem(pd^.para^.first);
3638 while assigned(para) do
3640 if para^.paratype.def^.deftype = formaldef then
3642 if para^.paratyp=vs_var then
3643 argnames := argnames+'3var'
3644 else if para^.paratyp=vs_const then
3645 argnames:=argnames+'5const';
3649 { if the arg definition is like (v: ^byte;..
3650 there is no sym attached to data !!! }
3651 if assigned(para^.paratype.def^.typesym) then
3653 arglength := length(para^.paratype.def^.typesym^.name);
3654 argnames := argnames + tostr(arglength)+para^.paratype.def^.typesym^.name;
3658 argnames:=argnames+'11unnamedtype';
3661 para := pparaitem(para^.next);
3663 ipd^.is_def_stab_written := written;
3664 { here 2A must be changed for private and protected }
3665 { 0 is private 1 protected and 2 public }
3666 if (sp_private in psym(p)^.symoptions) then sp:='0'
3667 else if (sp_protected in psym(p)^.symoptions) then sp:='1'
3669 newrec := strpnew(p^.name+'::'+ipd^.numberstring
3670 +'=##'+pd^.rettype.def^.numberstring+';:'+argnames+';'+sp+'A'
3672 { get spare place for a string at the end }
3673 if strlen(StabRecString) + strlen(newrec) >= StabRecSize-256 then
3675 getmem(news,stabrecsize+memsizeinc);
3676 strcopy(news,stabrecstring);
3677 freemem(stabrecstring,stabrecsize);
3678 stabrecsize:=stabrecsize+memsizeinc;
3679 stabrecstring:=news;
3681 strcat(StabRecstring,newrec);
3682 {freemem(newrec,memsizeinc); }
3688 function tobjectdef.stabstring : pchar;
3689 var anc : pobjectdef;
3691 oldrecsize,oldrecoffset : longint;
3694 if not (is_class) or writing_class_record_stab then
3696 oldrec := stabrecstring;
3697 oldrecsize:=stabrecsize;
3698 stabrecsize:=memsizeinc;
3699 GetMem(stabrecstring,stabrecsize);
3700 strpcopy(stabRecString,'s'+tostr(symtable^.datasize));
3701 if assigned(childof) then
3703 {only one ancestor not virtual, public, at base offset 0 }
3705 strpcopy(strend(stabrecstring),'!1,020,'+childof^.classnumberstring+';');
3707 OldRecOffset:=RecOffset;
3709 symtable^.foreach({$ifndef TP}@{$endif}addname);
3710 RecOffset:=OldRecOffset;
3711 if (oo_has_vmt in objectoptions) then
3712 if not assigned(childof) or not(oo_has_vmt in childof^.objectoptions) then
3714 strpcopy(strend(stabrecstring),'$vf'+classnumberstring+':'+typeglobalnumber('vtblarray')
3715 +','+tostr(vmt_offset*8)+';');
3717 symtable^.foreach({$ifndef TP}@{$endif}addprocname);
3718 if (oo_has_vmt in objectoptions) then
3721 while assigned(anc^.childof) and (oo_has_vmt in anc^.childof^.objectoptions) do
3722 anc := anc^.childof;
3723 { just in case anc = self }
3724 str_end:=';~%'+anc^.classnumberstring+';';
3728 strpcopy(strend(stabrecstring),str_end);
3729 stabstring := strnew(StabRecString);
3730 freemem(stabrecstring,stabrecsize);
3731 stabrecstring := oldrec;
3732 stabrecsize:=oldrecsize;
3736 stabstring:=strpnew('*'+classnumberstring);
3740 procedure tobjectdef.set_globalnb;
3742 globalnb:=PglobalTypeCount^;
3743 inc(PglobalTypeCount^);
3744 { classes need two type numbers, the globalnb is set to the ptr }
3747 globalnb:=PGlobalTypeCount^;
3748 inc(PglobalTypeCount^);
3752 function tobjectdef.classnumberstring : string;
3754 { write stabs again if needed }
3759 classnumberstring:=numberstring;
3763 classnumberstring:=numberstring;
3766 function tobjectdef.allstabstring : pchar;
3767 var stabchar : string[2];
3770 sym_line_no : longint;
3773 getmem(st,strlen(ss)+512);
3775 if deftype in tagtypes then
3777 if assigned(typesym) then
3779 sname := typesym^.name;
3780 sym_line_no:=typesym^.fileinfo.line;
3787 if writing_class_record_stab then
3788 strpcopy(st,'"'+sname+':'+stabchar+classnumberstring+'=')
3790 strpcopy(st,'"'+sname+':'+stabchar+numberstring+'=');
3791 strpcopy(strecopy(strend(st),ss),'",'+tostr(N_LSYM)+',0,'+tostr(sym_line_no)+',0');
3792 allstabstring := strnew(st);
3793 freemem(st,strlen(ss)+512);
3797 procedure tobjectdef.concatstabto(asmlist : paasmoutput);
3800 if not(is_class) then
3802 inherited concatstabto(asmlist);
3806 if ((typesym=nil) or typesym^.isusedinstab or (cs_gdb_dbx in aktglobalswitches)) and
3807 (is_def_stab_written = not_written) then
3811 { Write the record class itself }
3812 writing_class_record_stab:=true;
3813 inherited concatstabto(asmlist);
3814 writing_class_record_stab:=false;
3815 { Write the invisible pointer class }
3816 is_def_stab_written:=not_written;
3817 if assigned(typesym) then
3820 typesym^._name:=stringdup(' ');
3822 inherited concatstabto(asmlist);
3823 if assigned(typesym) then
3825 stringdispose(typesym^._name);
3833 procedure tobjectdef.write_child_init_data;
3835 symtable^.foreach({$ifndef TP}@{$endif}generate_child_inittable);
3839 procedure tobjectdef.write_init_data;
3842 rttilist^.concat(new(pai_const,init_8bit(tkclass)))
3844 rttilist^.concat(new(pai_const,init_8bit(tkobject)));
3846 { generate the name }
3847 rttilist^.concat(new(pai_const,init_8bit(length(objname^))));
3848 rttilist^.concat(new(pai_string,init(objname^)));
3850 rttilist^.concat(new(pai_const,init_32bit(size)));
3852 symtable^.foreach({$ifndef TP}@{$endif}count_inittable_fields);
3853 rttilist^.concat(new(pai_const,init_32bit(count)));
3854 symtable^.foreach({$ifndef TP}@{$endif}write_field_inittable);
3858 function tobjectdef.needs_inittable : boolean;
3863 needs_inittable:=false
3866 { there are recursive calls to needs_inittable possible, }
3867 { so we have to change to old value how else should }
3868 { we do that ? check_rec_rtti can't be a nested }
3869 { procedure of needs_rtti ! }
3872 symtable^.foreach({$ifndef TP}@{$endif}check_rec_inittable);
3873 needs_inittable:=binittable;
3879 procedure count_published_properties(sym:pnamedindexobject);
3880 {$ifndef fpc}far;{$endif}
3882 if needs_prop_entry(psym(sym)) and
3883 (psym(sym)^.typ<>varsym) then
3888 procedure write_property_info(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
3890 proctypesinfo : byte;
3892 procedure writeproc(proc : psymlist; shiftvalue : byte);
3900 if not(assigned(proc) and assigned(proc^.firstsym)) then
3902 rttilist^.concat(new(pai_const,init_32bit(1)));
3905 else if proc^.firstsym^.sym^.typ=varsym then
3909 while assigned(hp) do
3911 inc(address,pvarsym(hp^.sym)^.address);
3914 rttilist^.concat(new(pai_const,init_32bit(address)));
3919 if not(po_virtualmethod in pprocdef(proc^.def)^.procoptions) then
3921 rttilist^.concat(new(pai_const_symbol,initname(pprocdef(proc^.def)^.mangledname)));
3926 { virtual method, write vmt offset }
3927 rttilist^.concat(new(pai_const,init_32bit(
3928 pprocdef(proc^.def)^._class^.vmtmethodoffset(pprocdef(proc^.def)^.extnumber))));
3932 proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
3936 if needs_prop_entry(psym(sym)) then
3937 case psym(sym)^.typ of
3941 if not(pvarsym(sym)^.vartype.def^.deftype=objectdef) or
3942 not(pobjectdef(pvarsym(sym)^.vartype.def)^.is_class) then
3943 internalerror(1509992);
3944 { access to implicit class property as field }
3945 proctypesinfo:=(0 shl 0) or (0 shl 2) or (0 shl 4);
3946 rttilist^.concat(new(pai_const_symbol,initname(pvarsym(sym)^.vartype.def^.get_rtti_label)));
3947 rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
3948 rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
3949 { per default stored }
3950 rttilist^.concat(new(pai_const,init_32bit(1)));
3951 { index as well as ... }
3952 rttilist^.concat(new(pai_const,init_32bit(0)));
3953 { default value are zero }
3954 rttilist^.concat(new(pai_const,init_32bit(0)));
3955 rttilist^.concat(new(pai_const,init_16bit(count)));
3957 rttilist^.concat(new(pai_const,init_8bit(proctypesinfo)));
3958 rttilist^.concat(new(pai_const,init_8bit(length(pvarsym(sym)^.name))));
3959 rttilist^.concat(new(pai_string,init(pvarsym(sym)^.name)));
3964 if ppo_indexed in ppropertysym(sym)^.propoptions then
3968 rttilist^.concat(new(pai_const_symbol,initname(ppropertysym(sym)^.proptype.def^.get_rtti_label)));
3969 writeproc(ppropertysym(sym)^.readaccess,0);
3970 writeproc(ppropertysym(sym)^.writeaccess,2);
3971 { isn't it stored ? }
3972 if not(ppo_stored in ppropertysym(sym)^.propoptions) then
3974 rttilist^.concat(new(pai_const,init_32bit(0)));
3975 proctypesinfo:=proctypesinfo or (3 shl 4);
3978 writeproc(ppropertysym(sym)^.storedaccess,4);
3979 rttilist^.concat(new(pai_const,init_32bit(ppropertysym(sym)^.index)));
3980 rttilist^.concat(new(pai_const,init_32bit(ppropertysym(sym)^.default)));
3981 rttilist^.concat(new(pai_const,init_16bit(count)));
3983 rttilist^.concat(new(pai_const,init_8bit(proctypesinfo)));
3984 rttilist^.concat(new(pai_const,init_8bit(length(ppropertysym(sym)^.name))));
3985 rttilist^.concat(new(pai_string,init(ppropertysym(sym)^.name)));
3987 else internalerror(1509992);
3992 procedure generate_published_child_rtti(sym : pnamedindexobject);{$ifndef fpc}far;{$endif}
3994 if needs_prop_entry(psym(sym)) then
3995 case psym(sym)^.typ of
3999 pvarsym(sym)^.vartype.def^.get_rtti_label;
4002 ppropertysym(sym)^.proptype.def^.get_rtti_label;
4004 internalerror(1509991);
4009 procedure tobjectdef.write_child_rtti_data;
4011 symtable^.foreach({$ifndef TP}@{$endif}generate_published_child_rtti);
4015 procedure tobjectdef.generate_rtti;
4017 if not has_rtti then
4020 getdatalabel(rtti_label);
4021 write_child_rtti_data;
4022 rttilist^.concat(new(pai_symbol,initname_global(rtti_name,0)));
4023 rttilist^.concat(new(pai_label,init(rtti_label)));
4025 rttilist^.concat(new(pai_symbol_end,initname(rtti_name)));
4030 tclasslistitem = object(tlinkedlist_item)
4034 pclasslistitem = ^tclasslistitem;
4037 classtablelist : tlinkedlist;
4038 tablecount : longint;
4040 function searchclasstablelist(p : pobjectdef) : pclasslistitem;
4043 hp : pclasslistitem;
4046 hp:=pclasslistitem(classtablelist.first);
4047 while assigned(hp) do
4050 searchclasstablelist:=hp;
4054 hp:=pclasslistitem(hp^.next);
4055 searchclasstablelist:=nil;
4058 procedure count_published_fields(sym:pnamedindexobject);
4059 {$ifndef fpc}far;{$endif}
4062 hp : pclasslistitem;
4065 if needs_prop_entry(psym(sym)) and
4066 (psym(sym)^.typ=varsym) then
4068 if pvarsym(sym)^.vartype.def^.deftype<>objectdef then
4069 internalerror(0206001);
4070 hp:=searchclasstablelist(pobjectdef(pvarsym(sym)^.vartype.def));
4071 if not(assigned(hp)) then
4073 hp:=new(pclasslistitem,init);
4074 hp^.p:=pobjectdef(pvarsym(sym)^.vartype.def);
4075 hp^.index:=tablecount;
4076 classtablelist.concat(hp);
4083 procedure writefields(sym:pnamedindexobject);
4084 {$ifndef fpc}far;{$endif}
4087 hp : pclasslistitem;
4090 if needs_prop_entry(psym(sym)) and
4091 (psym(sym)^.typ=varsym) then
4093 rttilist^.concat(new(pai_const,init_32bit(pvarsym(sym)^.address)));
4094 hp:=searchclasstablelist(pobjectdef(pvarsym(sym)^.vartype.def));
4095 if not(assigned(hp)) then
4096 internalerror(0206002);
4097 rttilist^.concat(new(pai_const,init_16bit(hp^.index)));
4098 rttilist^.concat(new(pai_const,init_8bit(length(pvarsym(sym)^.name))));
4099 rttilist^.concat(new(pai_string,init(pvarsym(sym)^.name)));
4103 function tobjectdef.generate_field_table : pasmlabel;
4107 classtable : pasmlabel;
4108 hp : pclasslistitem;
4111 classtablelist.init;
4112 getdatalabel(fieldtable);
4113 getdatalabel(classtable);
4116 symtable^.foreach({$ifdef FPC}@{$endif}count_published_fields);
4117 rttilist^.concat(new(pai_label,init(fieldtable)));
4118 rttilist^.concat(new(pai_const,init_16bit(count)));
4119 rttilist^.concat(new(pai_const_symbol,init(classtable)));
4120 symtable^.foreach({$ifdef FPC}@{$endif}writefields);
4122 { generate the class table }
4123 rttilist^.concat(new(pai_label,init(classtable)));
4124 rttilist^.concat(new(pai_const,init_16bit(tablecount)));
4125 hp:=pclasslistitem(classtablelist.first);
4126 while assigned(hp) do
4128 rttilist^.concat(new(pai_const_symbol,initname(pobjectdef(hp^.p)^.vmt_mangledname)));
4129 hp:=pclasslistitem(hp^.next);
4132 generate_field_table:=fieldtable;
4133 classtablelist.done;
4136 function tobjectdef.next_free_name_index : longint;
4140 if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
4141 i:=childof^.next_free_name_index
4145 symtable^.foreach({$ifndef TP}@{$endif}count_published_properties);
4146 next_free_name_index:=i+count;
4150 procedure tobjectdef.write_rtti_data;
4153 rttilist^.concat(new(pai_const,init_8bit(tkclass)))
4155 rttilist^.concat(new(pai_const,init_8bit(tkobject)));
4157 { generate the name }
4158 rttilist^.concat(new(pai_const,init_8bit(length(objname^))));
4159 rttilist^.concat(new(pai_string,init(objname^)));
4161 { write class type }
4162 rttilist^.concat(new(pai_const_symbol,initname(vmt_mangledname)));
4164 { write owner typeinfo }
4165 if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
4166 rttilist^.concat(new(pai_const_symbol,initname(childof^.get_rtti_label)))
4168 rttilist^.concat(new(pai_const,init_32bit(0)));
4170 { count total number of properties }
4171 if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
4172 count:=childof^.next_free_name_index
4177 symtable^.foreach({$ifndef TP}@{$endif}count_published_properties);
4178 rttilist^.concat(new(pai_const,init_16bit(count)));
4181 if assigned(owner^.name) then
4183 rttilist^.concat(new(pai_const,init_8bit(length(owner^.name^))));
4184 rttilist^.concat(new(pai_string,init(owner^.name^)));
4187 rttilist^.concat(new(pai_const,init_8bit(0)));
4189 { write published properties count }
4191 symtable^.foreach({$ifndef TP}@{$endif}count_published_properties);
4192 rttilist^.concat(new(pai_const,init_16bit(count)));
4194 { count is used to write nameindex }
4195 { but we need an offset of the owner }
4196 { to give each property an own slot }
4197 if assigned(childof) and (oo_can_have_published in childof^.objectoptions) then
4198 count:=childof^.next_free_name_index
4202 symtable^.foreach({$ifndef TP}@{$endif}write_property_info);
4206 function tobjectdef.is_publishable : boolean;
4208 is_publishable:=is_class;
4211 function tobjectdef.get_rtti_label : string;
4215 get_rtti_label:=rtti_name;
4218 {****************************************************************************
4220 ****************************************************************************}
4222 constructor tforwarddef.init(const s:string;const pos : tfileposinfo);
4224 oldregisterdef : boolean;
4226 { never register the forwarddefs, they are disposed at the
4227 end of the type declaration block }
4228 oldregisterdef:=registerdef;
4231 registerdef:=oldregisterdef;
4232 deftype:=forwarddef;
4238 function tforwarddef.gettypename:string;
4240 gettypename:='unresolved forward to '+tosymname;
4244 {****************************************************************************
4246 ****************************************************************************}
4248 constructor terrordef.init;
4256 function terrordef.stabstring : pchar;
4258 stabstring:=strpnew('error'+numberstring);
4262 function terrordef.gettypename:string;
4265 gettypename:='<erroneous type>';
4270 Revision 1.1 2002/02/19 08:23:51 sasu
4273 Revision 1.1.2.17 2000/12/18 17:59:54 peter
4274 * removed unused var
4276 Revision 1.1.2.16 2000/11/26 18:13:47 florian
4277 * rtti for chars fixed
4279 Revision 1.1.2.15 2000/11/20 16:20:48 pierre
4280 + add size specifer for stabs of enums and sets
4282 Revision 1.1.2.14 2000/11/17 23:14:44 pierre
4283 * class stabs fix try
4285 Revision 1.1.2.13 2000/10/16 19:43:03 pierre
4286 * trying to correct class stabss once more
4288 Revision 1.1.2.12 2000/10/14 00:40:46 pierre
4289 * fixes for class debugging
4291 Revision 1.1.2.11 2000/10/13 12:08:42 peter
4292 * class stabsnumbering fixed partly
4294 Revision 1.1.2.10 2000/10/12 23:06:21 florian
4295 * type mismatch with procedure variables gives a more descriptive message now
4297 Revision 1.1.2.9 2000/10/04 22:55:42 pierre
4300 Revision 1.1.2.8 2000/09/19 22:26:27 pierre
4301 * fix for the local class debugging problem
4303 Revision 1.1.2.7 2000/09/10 20:12:26 peter
4304 * fixed array of const writing instead of array of tvarrec
4306 Revision 1.1.2.6 2000/09/09 18:39:46 peter
4307 * fixed C alignment of array of record
4309 Revision 1.1.2.5 2000/08/21 08:09:47 pierre
4310 * fix stabs problems
4312 Revision 1.1.2.4 2000/08/18 12:56:31 pierre
4313 * avoid infinite recursion in stabs generation
4315 Revision 1.1.2.3 2000/08/16 18:26:01 peter
4316 * splitted namedobjectitem.next into indexnext and listnext so it
4317 can be used in both lists
4318 * don't allow "word = word" type definitions
4320 Revision 1.1.2.2 2000/08/08 19:20:06 peter
4321 * setmangledname doesn't set parast,localst anymore (only in extdebug)
4323 Revision 1.1.2.1 2000/08/06 14:14:09 peter
4324 * hasforward added to check if a proc had a forward decl
4326 Revision 1.1 2000/07/13 06:29:56 michael
4329 Revision 1.205 2000/06/30 22:11:29 peter
4330 * fixed some getlabel to getdatalabel
4332 Revision 1.204 2000/06/29 08:42:47 sg
4333 * Fix for class field table writing
4335 Revision 1.203 2000/06/25 09:25:29 peter
4336 * setdef.typename, show Empty Set if elementtype is not set
4338 Revision 1.202 2000/06/22 20:01:57 peter
4339 * int64,qword rtti support
4341 Revision 1.201 2000/06/18 18:11:32 peter
4342 * C record packing fixed to also check first entry of the record
4343 if bigger than the recordalignment itself
4344 * variant record alignment uses alignment per variant and saves the
4345 highest alignment value
4347 Revision 1.200 2000/06/02 18:48:47 florian
4348 + fieldtable support for classes
4350 Revision 1.199 2000/04/01 14:17:08 peter
4351 * arraydef.elesize returns 4 when strings are found in an openarray,
4352 arrayconstructor. Since only the pointers to the strings are stored
4354 Revision 1.198 2000/04/01 11:44:56 peter
4355 * fixed rtti info for record
4357 Revision 1.197 2000/03/01 12:35:45 pierre
4360 Revision 1.196 2000/02/14 20:58:43 marco
4361 * Basic structures for new sethandling implemented.
4363 Revision 1.195 2000/02/11 13:53:49 pierre
4364 * avoid stack overflow in tref.done (bug 846)
4366 Revision 1.194 2000/02/09 13:23:04 peter
4369 Revision 1.193 2000/02/05 14:33:32 florian
4370 * fixed init table generation for classes and arrays
4372 Revision 1.192 2000/02/04 20:00:22 florian
4373 * an exception in a construcor calls now the destructor (this applies only
4376 Revision 1.191 2000/01/30 23:29:06 peter
4377 * fixed dup rtti writing for classes
4379 Revision 1.190 2000/01/28 23:17:53 florian
4380 * virtual XXXX; support for objects, only if -dWITHDMT is defined
4382 Revision 1.189 2000/01/26 12:02:29 peter
4383 * abstractprocdef.para_size needs alignment parameter
4384 * secondcallparan gets para_alignment size instead of dword_align
4386 Revision 1.188 2000/01/23 16:35:31 peter
4387 * localbrowser loading of absolute fixed. It needed a symtablestack
4388 which was not setup correctly
4390 Revision 1.187 2000/01/09 23:16:06 peter
4391 * added st_default stringtype
4392 * genstringconstnode extended with stringtype parameter using st_default
4393 will do the old behaviour
4395 Revision 1.186 2000/01/07 01:14:39 peter
4396 * updated copyright to 2000
4398 Revision 1.185 2000/01/03 19:26:03 peter
4399 * fixed resolving of ttypesym which are reference from object/record
4402 Revision 1.184 1999/12/31 14:24:34 peter
4403 * fixed rtti generation for classes with no published section
4405 Revision 1.183 1999/12/23 12:19:42 peter
4406 * check_rec_inittable fix from sg
4408 Revision 1.182 1999/12/19 17:00:27 peter
4409 * has_rtti should be saved in the ppu for objects
4411 Revision 1.181 1999/12/18 14:55:21 florian
4412 * very basic widestring support
4414 Revision 1.180 1999/12/06 18:21:03 peter
4415 * support !ENVVAR for long commandlines
4416 * win32/go32v2 write short pathnames to link.res so c:\Program Files\ is
4417 finally supported as installdir.
4419 Revision 1.179 1999/12/01 12:42:33 peter
4421 * removed some notes about unused vars
4423 Revision 1.178 1999/12/01 10:26:38 pierre
4424 * restore the correct way for stabs of forward defs
4426 Revision 1.177 1999/11/30 10:40:54 peter
4429 Revision 1.176 1999/11/09 23:35:49 pierre
4430 + better reference pos for forward defs
4432 Revision 1.175 1999/11/07 23:57:36 pierre
4433 + higher level browser
4435 Revision 1.174 1999/11/06 14:34:26 peter
4436 * truncated log to 20 revs