symtable.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. {
  2. $Id$
  3. Copyright (C) 1998-2000 by Florian Klaempfl, Daniel Mantione,
  4. Pierre Muller and other members of the Free Pascal development team
  5. This unit handles the symbol tables
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. {$ifdef TP}
  20. {$N+,E+,F+}
  21. {$endif}
  22. unit symtable;
  23. interface
  24. uses objects{$IFDEF TP},xobjects{$ENDIF}
  25. ,cobjects,aasm,globtype,cpubase;
  26. type Tdefprop=(dp_regable, {Can be stored into a register.}
  27. dp_pointer_param, {A pointer should be used
  28. instead of the value for
  29. parameters of this definition.}
  30. dp_ret_in_acc); {Function results of this
  31. definition can be returned into
  32. the accumulator.}
  33. Tdefpropset=set of Tdefprop;
  34. Psymtable=^Tsymtable;
  35. Pcontainingsymtable=^Tcontainingsymtable;
  36. Pref=^Tref;
  37. Psymtableentry=^Tsymtableentry;
  38. Psym=^Tsym;
  39. Pdef=^Tdef;
  40. Tsymtable=object(Tobject)
  41. name:Pstring;
  42. datasize:longint;
  43. {$IFDEF TP}
  44. constructor init;
  45. {$ENDIF TP}
  46. procedure foreach(proc2call:Tnamedindexcallback);virtual;
  47. function insert(sym:Psym):boolean;virtual;
  48. function search(const s:stringid):Psym;
  49. function speedsearch(const s:stringid;
  50. speedvalue:longint):Psym;virtual;
  51. function tconstsymtodata(sym:Psym;len:longint):longint;virtual;
  52. function varsymprefix:string;virtual;
  53. function varsymtodata(sym:Psym;len:longint):longint;virtual;
  54. end;
  55. Tcontainingsymtable=object(Tsymtable)
  56. alignment:byte; {Aligment used in this symtable.}
  57. index_growsize:word; {The delta of the defindex collection.}
  58. defindex:Pcollection; {Contains all definitions in symtable.}
  59. symsearch:Pdictionary;
  60. constructor init;
  61. constructor load(var s:Tstream);
  62. procedure set_contents(s:Pdictionary;d:Pcollection);
  63. {Get_contents disposes the symtable object!!}
  64. procedure get_contents(var s:Pdictionary;var d:Pcollection);
  65. {Checks if all variabeles are used.}
  66. procedure check_vars;
  67. {Checks if all forwards resolved.}
  68. procedure check_forwards;
  69. {Checks if all labels used.}
  70. procedure check_labels;
  71. procedure foreach(proc2call:Tnamedindexcallback);virtual;
  72. function insert(sym:Psym):boolean;virtual;
  73. function speedsearch(const s:stringid;
  74. speedvalue:longint):Psym;virtual;
  75. procedure store(var s:Tstream);virtual;
  76. procedure registerdef(p:Pdef);
  77. destructor done;virtual;
  78. end;
  79. Tref=object(Tobject)
  80. posinfo:Tfileposinfo;
  81. moduleindex:word;
  82. constructor init(const pos:Tfileposinfo);
  83. destructor done;virtual;
  84. end;
  85. Tsymtableentry=object(Tnamedindexobject)
  86. owner:Pcontainingsymtable;
  87. {$IFDEF TP}
  88. constructor init(const n:string);
  89. {$ENDIF TP}
  90. end;
  91. Tsymprop=byte;
  92. Tsym=object(Tsymtableentry)
  93. fileinfo:Tfileposinfo;
  94. references:Pcollection; {Contains all references to symbol.}
  95. constructor init(const n : string);
  96. constructor load(var s:Tstream);
  97. procedure deref;virtual;
  98. procedure make_reference;
  99. function mangledname:string;virtual;
  100. procedure insert_in_data;virtual;
  101. procedure load_references;virtual;
  102. procedure register_defs;virtual;
  103. procedure store(var s:Tstream);virtual;
  104. function write_references:boolean;virtual;
  105. {$ifdef BrowserLog}
  106. procedure add_to_browserlog;virtual;
  107. {$endif BrowserLog}
  108. destructor done;virtual;
  109. end;
  110. Tdef=object(Tobject)
  111. savesize:longint;
  112. sym:Psym;
  113. owner:Pcontainingsymtable;
  114. properties:Tdefpropset;
  115. inittable:Pasmlabel; {Nil, or pointer to inittable.}
  116. rtti:Pasmlabel; {Nil, or pointer to rtti.}
  117. constructor init(Aowner:Pcontainingsymtable);
  118. constructor load(var s:Tstream);
  119. destructor done;virtual;
  120. {procedure correct_owner_symtable; REMOVED
  121. enumdefs can be safely in a record or object symtable,
  122. but the enum symbols must be in owners symtable.}
  123. procedure store(var s:Tstream);virtual;
  124. {Returns the typename of this definition.}
  125. function typename:string;virtual;
  126. procedure deref;virtual;
  127. function size:longint;virtual;
  128. procedure symderef;virtual;
  129. {Init. tables }
  130. function needs_inittable:boolean;virtual;
  131. procedure generate_inittable;
  132. function get_inittable_label:Pasmlabel;
  133. {The default implemenation calls write_rtti_data
  134. if init and rtti data is different these procedures
  135. must be overloaded.}
  136. procedure write_init_data;virtual;
  137. {Writes rtti of child to avoid mixup of rtti.}
  138. procedure write_child_init_data;virtual;
  139. {Rtti}
  140. procedure write_rtti_name;
  141. function get_rtti_label:string;virtual;
  142. procedure generate_rtti;virtual;
  143. procedure write_rtti_data;virtual;
  144. procedure write_child_rtti_data;virtual;
  145. { returns true, if the definition can be published }
  146. function is_publishable : boolean;virtual;
  147. function gettypename:string;virtual;
  148. end;
  149. const systemunit:Psymtable = nil; {Pointer to the system unit.}
  150. objpasunit:Psymtable = nil; {Pointer to the objpas unit.}
  151. macros:Psymtable = nil; {Pointer to macro list.}
  152. const defalignment=4;
  153. var read_member : boolean; {True, wenn Members aus einer PPU-
  154. Datei gelesen werden, d.h. ein
  155. varsym seine Adresse einlesen soll }
  156. procprefix:stringid;
  157. generrorsym:Psym; {Jokersymbol, wenn das richtige
  158. symbol nicht gefunden wird.}
  159. generrordef:Pdef; {Jokersymbol for eine fehlerhafte
  160. typdefinition.}
  161. procedure duplicatesym(sym:psym);
  162. {**************************************************************************}
  163. implementation
  164. {**************************************************************************}
  165. uses symtablt,files,verbose,globals;
  166. {****************************************************************************
  167. Tsymtable
  168. ****************************************************************************}
  169. {$IFDEF TP}
  170. constructor Tsymtable.init;
  171. begin
  172. setparent(typeof(Tobject));
  173. end;
  174. {$ENDIF TP}
  175. procedure Tsymtable.foreach(proc2call:Tnamedindexcallback);
  176. begin
  177. abstract;
  178. end;
  179. function Tsymtable.insert(sym:Psym):boolean;
  180. begin
  181. abstract;
  182. end;
  183. function Tsymtable.search(const s:stringid):Psym;
  184. begin
  185. search:=speedsearch(s,getspeedvalue(s));
  186. end;
  187. function Tsymtable.speedsearch(const s:stringid;speedvalue:longint):Psym;
  188. begin
  189. abstract;
  190. end;
  191. function Tsymtable.tconstsymtodata(sym:Psym;len:longint):longint;
  192. begin
  193. tconstsymtodata:=datasize;
  194. inc(datasize,len);
  195. end;
  196. function Tsymtable.varsymprefix:string;
  197. begin
  198. abstract;
  199. end;
  200. function Tsymtable.varsymtodata(sym:Psym;len:longint):longint;
  201. begin
  202. varsymtodata:=datasize;
  203. inc(datasize,len);
  204. end;
  205. {****************************************************************************
  206. Tcontainingsymtable
  207. ****************************************************************************}
  208. constructor Tcontainingsymtable.init;
  209. var indexgrow:word;
  210. begin
  211. inherited init;
  212. {$IFDEF TP}setparent(typeof(Tsymtable));{$ENDIF}
  213. indexgrow:=index_growsize;
  214. new(defindex,init(2*indexgrow,indexgrow));
  215. new(symsearch,init);
  216. alignment:=defalignment;
  217. index_growsize:=16;
  218. end;
  219. constructor Tcontainingsymtable.load;
  220. begin
  221. end;
  222. procedure Tcontainingsymtable.get_contents(var s:Pdictionary;
  223. var d:Pcollection);
  224. begin
  225. s:=symsearch;
  226. d:=defindex;
  227. free;
  228. end;
  229. procedure Tcontainingsymtable.store(var s:Tstream);
  230. begin
  231. end;
  232. procedure Tcontainingsymtable.check_vars;
  233. begin
  234. end;
  235. procedure Tcontainingsymtable.check_forwards;
  236. begin
  237. end;
  238. procedure Tcontainingsymtable.check_labels;
  239. begin
  240. end;
  241. procedure Tcontainingsymtable.foreach(proc2call:Tnamedindexcallback);
  242. begin
  243. symsearch^.foreach(proc2call);
  244. end;
  245. function Tcontainingsymtable.insert(sym:Psym):boolean;
  246. begin
  247. insert:=true;
  248. if symsearch^.insert(sym)<>Pnamedindexobject(sym) then
  249. begin
  250. duplicatesym(sym);
  251. insert:=false;
  252. end
  253. else
  254. begin
  255. sym^.owner:=@self;
  256. sym^.register_defs;
  257. end;
  258. end;
  259. procedure Tcontainingsymtable.set_contents(s:Pdictionary;d:Pcollection);
  260. begin
  261. dispose(defindex,done);
  262. dispose(symsearch,done);
  263. defindex:=d;
  264. symsearch:=s;
  265. end;
  266. function Tcontainingsymtable.speedsearch(const s:stringid;
  267. speedvalue:longint):Psym;
  268. var r:Psym;
  269. begin
  270. r:=Psym(symsearch^.speedsearch(s,speedvalue));
  271. {Make a notice that the symbol is referenced.}
  272. if (r<>nil) and (cs_browser in aktmoduleswitches) and make_ref then
  273. r^.make_reference;
  274. speedsearch:=r;
  275. end;
  276. procedure Tcontainingsymtable.registerdef(p:Pdef);
  277. begin
  278. defindex^.insert(p);
  279. p^.owner:=@self;
  280. end;
  281. destructor Tcontainingsymtable.done;
  282. begin
  283. dispose(defindex,done);
  284. dispose(symsearch,done);
  285. inherited done;
  286. end;
  287. {****************************************************************************
  288. Tref
  289. ****************************************************************************}
  290. constructor Tref.init(const pos:Tfileposinfo);
  291. begin
  292. inherited init;
  293. {$IFDEF TP}setparent(typeof(Tobject));{$ENDIF}
  294. posinfo:=pos;
  295. moduleindex:=current_module^.unit_index;
  296. end;
  297. destructor Tref.done;
  298. var inputfile:Pinputfile;
  299. begin
  300. inputfile:=get_source_file(moduleindex,posinfo.fileindex);
  301. if inputfile<>nil then
  302. dec(inputfile^.ref_count);
  303. end;
  304. procedure duplicatesym(sym:Psym);
  305. begin
  306. message1(sym_e_duplicate_id,sym^.name);
  307. with sym^.fileinfo do
  308. message2(sym_h_duplicate_id_where,
  309. current_module^.sourcefiles^.get_file_name(fileindex),tostr(line));
  310. end;
  311. {****************************************************************************
  312. Tsymtableentry
  313. ****************************************************************************}
  314. {$IFDEF TP}
  315. constructor Tsymtableentry.init(const n:string);
  316. begin
  317. inherited init(n);
  318. setparent(typeof(Tnamedindexobject));
  319. end;
  320. {$ENDIF TP}
  321. {****************************************************************************
  322. Tsym
  323. ****************************************************************************}
  324. constructor Tsym.init(const n:string);
  325. begin
  326. inherited init(n);
  327. {$IFDEF TP}setparent(typeof(Tsymtableentry));{$ENDIF}
  328. fileinfo:=tokenpos;
  329. if cs_browser in aktmoduleswitches then
  330. new(references,init(32,16));
  331. {The place where a symbol is defined is also a reference. You can safely
  332. assume that the first reference in the references collection is the
  333. place where the symbol is defined.}
  334. make_reference;
  335. end;
  336. constructor Tsym.load(var s:Tstream);
  337. begin
  338. end;
  339. procedure Tsym.deref;
  340. begin
  341. abstract;
  342. end;
  343. procedure Tsym.insert_in_data;
  344. begin
  345. end;
  346. procedure Tsym.make_reference;
  347. begin
  348. if (cs_browser in aktmoduleswitches) and make_ref then
  349. references^.insert(new(Pref,init(tokenpos)));
  350. end;
  351. function Tsym.mangledname:string;
  352. begin
  353. mangledname:=name;
  354. end;
  355. procedure Tsym.register_defs;
  356. begin
  357. end;
  358. procedure Tsym.store(var s:Tstream);
  359. begin
  360. end;
  361. destructor Tsym.done;
  362. begin
  363. if references<>nil then
  364. dispose(references,done);
  365. inherited done;
  366. end;
  367. procedure Tsym.load_references;
  368. begin
  369. end;
  370. function Tsym.write_references:boolean;
  371. begin
  372. end;
  373. {****************************************************************************
  374. Tdef
  375. ****************************************************************************}
  376. constructor Tdef.init(Aowner:Pcontainingsymtable);
  377. begin
  378. inherited init;
  379. {$IFDEF TP}setparent(typeof(Tobject));{$ENDIF}
  380. Aowner^.registerdef(@self);
  381. owner:=Aowner;
  382. end;
  383. constructor Tdef.load;
  384. begin
  385. end;
  386. procedure Tdef.store(var s:Tstream);
  387. begin
  388. end;
  389. function Tdef.typename:string;
  390. begin
  391. typename:='<unknown type>';
  392. end;
  393. procedure Tdef.deref;
  394. begin
  395. end;
  396. function Tdef.size:longint;
  397. begin
  398. size:=savesize;
  399. end;
  400. procedure Tdef.symderef;
  401. begin
  402. end;
  403. function Tdef.needs_inittable:boolean;
  404. begin
  405. end;
  406. procedure Tdef.generate_inittable;
  407. begin
  408. end;
  409. function Tdef.get_inittable_label:Pasmlabel;
  410. begin
  411. end;
  412. procedure Tdef.write_init_data;
  413. begin
  414. end;
  415. procedure Tdef.write_child_init_data;
  416. begin
  417. end;
  418. procedure Tdef.write_rtti_name;
  419. begin
  420. end;
  421. function Tdef.get_rtti_label:string;
  422. begin
  423. end;
  424. procedure Tdef.generate_rtti;
  425. begin
  426. end;
  427. procedure Tdef.write_rtti_data;
  428. begin
  429. end;
  430. procedure Tdef.write_child_rtti_data;
  431. begin
  432. end;
  433. function Tdef.is_publishable:boolean;
  434. begin
  435. is_publishable:=false;
  436. end;
  437. function Tdef.gettypename:string;
  438. begin
  439. gettypename:='<unknown type>';
  440. end;
  441. destructor Tdef.done;
  442. {var s:Ptypesym;}
  443. begin
  444. { s:=sym;
  445. while s<>nil do
  446. begin
  447. s^.definition:=nil;
  448. s:=s^.synonym;
  449. end;}
  450. inherited done;
  451. end;
  452. end.