hcgdata.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Daniel Mantione,
  4. and other members of the Free Pascal development team
  5. Routines for the code generation of data structures
  6. like VMT,Messages
  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.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. ****************************************************************************
  19. }
  20. unit hcgdata;
  21. interface
  22. uses
  23. symtable,aasm,defs;
  24. { generates the message tables for a class }
  25. function genstrmsgtab(_class : pobjectdef) : pasmlabel;
  26. function genintmsgtab(_class : pobjectdef) : pasmlabel;
  27. { generates the method name table }
  28. function genpublishedmethodstable(Aclass:Pobjectdef):Pasmlabel;
  29. { generates a VMT for _class }
  30. procedure genvmt(list : paasmoutput;_class : pobjectdef);
  31. {$ifdef WITHDMT}
  32. { generates a DMT for _class }
  33. function gendmt(_class : pobjectdef) : pasmlabel;
  34. {$endif WITHDMT}
  35. implementation
  36. uses
  37. strings,cobjects,globtype,globals,verbose,
  38. types,hcodegen,symbols,objects,xobjects;
  39. {*****************************************************************************
  40. Message
  41. *****************************************************************************}
  42. type
  43. pprocdeftree = ^tprocdeftree;
  44. tprocdeftree = record
  45. p : pprocdef;
  46. nl : pasmlabel;
  47. l,r : pprocdeftree;
  48. end;
  49. var
  50. root : pprocdeftree;
  51. count : longint;
  52. procedure insertstr(p : pprocdeftree;var at : pprocdeftree);
  53. var
  54. i : longint;
  55. begin
  56. if at=nil then
  57. begin
  58. at:=p;
  59. inc(count);
  60. end
  61. else
  62. begin
  63. i:=strcomp(p^.p^.messageinf.str,at^.p^.messageinf.str);
  64. if i<0 then
  65. insertstr(p,at^.l)
  66. else if i>0 then
  67. insertstr(p,at^.r)
  68. else
  69. Message1(parser_e_duplicate_message_label,strpas(p^.p^.messageinf.str));
  70. end;
  71. end;
  72. procedure disposeprocdeftree(p : pprocdeftree);
  73. begin
  74. if assigned(p^.l) then
  75. disposeprocdeftree(p^.l);
  76. if assigned(p^.r) then
  77. disposeprocdeftree(p^.r);
  78. dispose(p);
  79. end;
  80. procedure insertmsgstr(p:pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  81. procedure inserter(p:pointer);{$IFDEF TP}far;{$ENDIF}
  82. var pt:Pprocdeftree;
  83. begin
  84. if po_msgstr in Pprocdef(p)^.options then
  85. begin
  86. new(pt);
  87. pt^.p:=p;
  88. pt^.l:=nil;
  89. pt^.r:=nil;
  90. insertstr(pt,root);
  91. end;
  92. end;
  93. begin
  94. if typeof(p^)=typeof(Tprocsym) then
  95. Pprocsym(p)^.foreach(@inserter);
  96. end;
  97. procedure insertint(p : pprocdeftree;var at : pprocdeftree);
  98. begin
  99. if at=nil then
  100. begin
  101. at:=p;
  102. inc(count);
  103. end
  104. else
  105. begin
  106. if p^.p^.messageinf.i<at^.p^.messageinf.i then
  107. insertint(p,at^.l)
  108. else if p^.p^.messageinf.i>at^.p^.messageinf.i then
  109. insertint(p,at^.r)
  110. else
  111. Message1(parser_e_duplicate_message_label,tostr(p^.p^.messageinf.i));
  112. end;
  113. end;
  114. procedure insertmsgint(p:pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  115. procedure inserter(p:pointer);{$IFDEF TP}far;{$ENDIF}
  116. var pt:Pprocdeftree;
  117. begin
  118. if po_msgint in Pprocdef(p)^.options then
  119. begin
  120. new(pt);
  121. pt^.p:=p;
  122. pt^.l:=nil;
  123. pt^.r:=nil;
  124. insertint(pt,root);
  125. end;
  126. end;
  127. begin
  128. if typeof(p^)=typeof(Tprocsym) then
  129. Pprocsym(p)^.foreach(@inserter);
  130. end;
  131. procedure writenames(p : pprocdeftree);
  132. begin
  133. getdatalabel(p^.nl);
  134. if assigned(p^.l) then
  135. writenames(p^.l);
  136. datasegment^.concat(new(pai_label,init(p^.nl)));
  137. datasegment^.concat(new(pai_const,init_8bit(strlen(p^.p^.messageinf.str))));
  138. datasegment^.concat(new(pai_string,init_pchar(p^.p^.messageinf.str)));
  139. if assigned(p^.r) then
  140. writenames(p^.r);
  141. end;
  142. procedure writestrentry(p : pprocdeftree);
  143. begin
  144. if assigned(p^.l) then
  145. writestrentry(p^.l);
  146. { write name label }
  147. datasegment^.concat(new(pai_const_symbol,init(p^.nl)));
  148. datasegment^.concat(new(pai_const_symbol,initname(p^.p^.mangledname)));
  149. if assigned(p^.r) then
  150. writestrentry(p^.r);
  151. end;
  152. function genstrmsgtab(_class : pobjectdef) : pasmlabel;
  153. var
  154. r : pasmlabel;
  155. begin
  156. root:=nil;
  157. count:=0;
  158. if _class^.privatesyms<>nil then
  159. _class^.privatesyms^.foreach({$ifndef TP}@{$endif}insertmsgstr);
  160. if _class^.privatesyms<>nil then
  161. _class^.protectedsyms^.foreach({$ifndef TP}@{$endif}insertmsgstr);
  162. if _class^.privatesyms<>nil then
  163. _class^.publicsyms^.foreach({$ifndef TP}@{$endif}insertmsgstr);
  164. { write all names }
  165. if assigned(root) then
  166. writenames(root);
  167. { now start writing of the message string table }
  168. getdatalabel(r);
  169. datasegment^.concat(new(pai_label,init(r)));
  170. genstrmsgtab:=r;
  171. datasegment^.concat(new(pai_const,init_32bit(count)));
  172. if assigned(root) then
  173. begin
  174. writestrentry(root);
  175. disposeprocdeftree(root);
  176. end;
  177. end;
  178. procedure writeintentry(p : pprocdeftree);
  179. begin
  180. if assigned(p^.l) then
  181. writeintentry(p^.l);
  182. { write name label }
  183. datasegment^.concat(new(pai_const,init_32bit(p^.p^.messageinf.i)));
  184. datasegment^.concat(new(pai_const_symbol,initname(p^.p^.mangledname)));
  185. if assigned(p^.r) then
  186. writeintentry(p^.r);
  187. end;
  188. function genintmsgtab(_class : pobjectdef) : pasmlabel;
  189. var
  190. r : pasmlabel;
  191. begin
  192. root:=nil;
  193. count:=0;
  194. if _class^.privatesyms<>nil then
  195. _class^.privatesyms^.foreach({$ifndef TP}@{$endif}insertmsgint);
  196. if _class^.privatesyms<>nil then
  197. _class^.protectedsyms^.foreach({$ifndef TP}@{$endif}insertmsgint);
  198. if _class^.privatesyms<>nil then
  199. _class^.publicsyms^.foreach({$ifndef TP}@{$endif}insertmsgint);
  200. { now start writing of the message string table }
  201. getdatalabel(r);
  202. datasegment^.concat(new(pai_label,init(r)));
  203. genintmsgtab:=r;
  204. datasegment^.concat(new(pai_const,init_32bit(count)));
  205. if assigned(root) then
  206. begin
  207. writeintentry(root);
  208. disposeprocdeftree(root);
  209. end;
  210. end;
  211. {$ifdef WITHDMT}
  212. procedure insertdmtentry(p : pnamedindexobject);{$ifndef FPC}far;{$endif FPC}
  213. var
  214. hp : pprocdef;
  215. pt : pprocdeftree;
  216. begin
  217. if psym(p)^.typ=procsym then
  218. begin
  219. hp:=pprocsym(p)^.definition;
  220. while assigned(hp) do
  221. begin
  222. if (po_msgint in hp^.procoptions) then
  223. begin
  224. new(pt);
  225. pt^.p:=hp;
  226. pt^.l:=nil;
  227. pt^.r:=nil;
  228. insertint(pt,root);
  229. end;
  230. hp:=hp^.nextoverloaded;
  231. end;
  232. end;
  233. end;
  234. procedure writedmtindexentry(p : pprocdeftree);
  235. begin
  236. if assigned(p^.l) then
  237. writedmtindexentry(p^.l);
  238. datasegment^.concat(new(pai_const,init_32bit(p^.p^.messageinf.i)));
  239. if assigned(p^.r) then
  240. writedmtindexentry(p^.r);
  241. end;
  242. procedure writedmtaddressentry(p : pprocdeftree);
  243. begin
  244. if assigned(p^.l) then
  245. writedmtaddressentry(p^.l);
  246. datasegment^.concat(new(pai_const_symbol,initname(p^.p^.mangledname)));
  247. if assigned(p^.r) then
  248. writedmtaddressentry(p^.r);
  249. end;
  250. function gendmt(_class : pobjectdef) : pasmlabel;
  251. var
  252. r : pasmlabel;
  253. begin
  254. root:=nil;
  255. count:=0;
  256. gendmt:=nil;
  257. { insert all message handlers into a tree, sorted by number }
  258. _class^.symtable^.foreach({$ifndef TP}@{$endif}insertdmtentry);
  259. if count>0 then
  260. begin
  261. getdatalabel(r);
  262. gendmt:=r;
  263. datasegment^.concat(new(pai_label,init(r)));
  264. { entries for caching }
  265. datasegment^.concat(new(pai_const,init_32bit(0)));
  266. datasegment^.concat(new(pai_const,init_32bit(0)));
  267. datasegment^.concat(new(pai_const,init_32bit(count)));
  268. if assigned(root) then
  269. begin
  270. writedmtindexentry(root);
  271. writedmtaddressentry(root);
  272. disposeprocdeftree(root);
  273. end;
  274. end;
  275. end;
  276. {$endif WITHDMT}
  277. procedure genpubmethodtableentry(p : pnamedindexobject);{$ifndef FPC}far;{$endif}
  278. procedure do_concat(q:pointer);{$ifndef FPC}far;{$endif}
  279. var l:Pasmlabel;
  280. begin
  281. if (sp_published in Pprocsym(p)^.objprop) then
  282. begin
  283. getlabel(l);
  284. consts^.concat(new(pai_label,init(l)));
  285. consts^.concat(new(pai_const,init_8bit(length(p^.name))));
  286. consts^.concat(new(pai_string,init(p^.name)));
  287. datasegment^.concat(new(pai_const_symbol,init(l)));
  288. datasegment^.concat(new(pai_const_symbol,initname(Pprocdef(q)^.mangledname)));
  289. end;
  290. end;
  291. begin
  292. if p^.is_object(typeof(Tprocsym)) then
  293. Pprocsym(p)^.foreach(@do_concat);
  294. end;
  295. procedure sym_do_count(p:Pnamedindexobject);{$ifndef FPC}far;{$endif}
  296. procedure def_do_count(p:pointer);{$ifndef FPC}far;{$endif}
  297. begin
  298. if (sp_published in Pprocsym(p)^.objprop) then
  299. inc(count);
  300. end;
  301. begin
  302. if Pobject(p)^.is_object(typeof(Tprocsym)) then
  303. Pprocsym(p)^.foreach(@def_do_count);
  304. end;
  305. function genpublishedmethodstable(Aclass:Pobjectdef):Pasmlabel;
  306. var l:Pasmlabel;
  307. begin
  308. count:=0;
  309. if Aclass^.privatesyms<>nil then
  310. Aclass^.privatesyms^.foreach({$ifndef TP}@{$endif}sym_do_count);
  311. if Aclass^.protectedsyms<>nil then
  312. Aclass^.publicsyms^.foreach({$ifndef TP}@{$endif}sym_do_count);
  313. if Aclass^.publicsyms<>nil then
  314. Aclass^.publicsyms^.foreach({$ifndef TP}@{$endif}sym_do_count);
  315. if count>0 then
  316. begin
  317. getlabel(l);
  318. datasegment^.concat(new(pai_label,init(l)));
  319. datasegment^.concat(new(pai_const,init_32bit(count)));
  320. if Aclass^.privatesyms<>nil then
  321. Aclass^.privatesyms^.foreach({$ifndef TP}@{$endif}genpubmethodtableentry);
  322. if Aclass^.protectedsyms<>nil then
  323. Aclass^.protectedsyms^.foreach({$ifndef TP}@{$endif}genpubmethodtableentry);
  324. if Aclass^.publicsyms<>nil then
  325. Aclass^.publicsyms^.foreach({$ifndef TP}@{$endif}genpubmethodtableentry);
  326. genpublishedmethodstable:=l;
  327. end
  328. else
  329. genpublishedmethodstable:=nil;
  330. end;
  331. {*****************************************************************************
  332. VMT
  333. *****************************************************************************}
  334. procedure genvmt(list:Paasmoutput;_class:Pobjectdef);
  335. var i:longint;
  336. begin
  337. for i:=0 to _class^.vmt_layout^.count-1 do
  338. list^.concat(new(pai_const_symbol,
  339. initname(Pvmtentry(_class^.vmt_layout^.at(i))^.mangledname)));
  340. end;
  341. end.
  342. {
  343. $Log$
  344. Revision 1.1 2000-07-13 06:30:13 michael
  345. + Initial import
  346. Revision 1.2 2000/03/16 12:52:48 daniel
  347. * Changed names of procedures flags
  348. * Changed VMT generation
  349. Revision 1.1 2000/03/11 21:11:25 daniel
  350. * Ported hcgdata to new symtable.
  351. * Alignment code changed as suggested by Peter
  352. + Usage of my is operator replacement, is_object
  353. }