symppu.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl, Pierre Muller
  4. Implementation of the reading of PPU Files for the symtable
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit symppu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cclasses,
  23. globtype,globals,
  24. cpuinfo,aasmbase,
  25. symbase,symtype,
  26. ppu;
  27. type
  28. tcompilerppufile=class(tppufile)
  29. public
  30. procedure checkerror;
  31. procedure getguid(var g: tguid);
  32. function getexprint:tconstexprint;
  33. function getptruint:TConstPtrUInt;
  34. procedure getposinfo(var p:tfileposinfo);
  35. function getderef : pointer;
  36. function getsymlist:tsymlist;
  37. procedure gettype(var t:ttype);
  38. function getasmsymbol:tasmsymbol;
  39. procedure putguid(const g: tguid);
  40. procedure putexprint(v:tconstexprint);
  41. procedure PutPtrUInt(v:TConstPtrUInt);
  42. procedure putposinfo(const p:tfileposinfo);
  43. procedure putderef(p : tsymtableentry);
  44. procedure putsymlist(p:tsymlist);
  45. procedure puttype(const t:ttype);
  46. procedure putasmsymbol(s:tasmsymbol);
  47. end;
  48. implementation
  49. uses
  50. symconst,
  51. verbose;
  52. {*****************************************************************************
  53. TCompilerPPUFile
  54. *****************************************************************************}
  55. procedure tcompilerppufile.checkerror;
  56. begin
  57. if error then
  58. Message(unit_f_ppu_read_error);
  59. end;
  60. procedure tcompilerppufile.getguid(var g: tguid);
  61. begin
  62. getdata(g,sizeof(g));
  63. end;
  64. function tcompilerppufile.getexprint:tconstexprint;
  65. var
  66. l1,l2 : longint;
  67. begin
  68. if sizeof(tconstexprint)=8 then
  69. begin
  70. l1:=getlongint;
  71. l2:=getlongint;
  72. {$ifopt R+}
  73. {$define Range_check_on}
  74. {$endif opt R+}
  75. {$R- needed here }
  76. result:=qword(l1)+(int64(l2) shl 32);
  77. {$ifdef Range_check_on}
  78. {$R+}
  79. {$undef Range_check_on}
  80. {$endif Range_check_on}
  81. end
  82. else
  83. result:=getlongint;
  84. end;
  85. function tcompilerppufile.getPtrUInt:TConstPtrUInt;
  86. var
  87. l1,l2 : longint;
  88. begin
  89. if sizeof(tconstexprint)=8 then
  90. begin
  91. l1:=getlongint;
  92. l2:=getlongint;
  93. {$ifopt R+}
  94. {$define Range_check_on}
  95. {$endif opt R+}
  96. {$R- needed here }
  97. result:=qword(l1)+(int64(l2) shl 32);
  98. {$ifdef Range_check_on}
  99. {$R+}
  100. {$undef Range_check_on}
  101. {$endif Range_check_on}
  102. end
  103. else
  104. result:=getlongint;
  105. end;
  106. procedure tcompilerppufile.getposinfo(var p:tfileposinfo);
  107. var
  108. info : byte;
  109. begin
  110. {
  111. info byte layout in bits:
  112. 0-1 - amount of bytes for fileindex
  113. 2-3 - amount of bytes for line
  114. 4-5 - amount of bytes for column
  115. }
  116. info:=getbyte;
  117. case (info and $03) of
  118. 0 : p.fileindex:=getbyte;
  119. 1 : p.fileindex:=getword;
  120. 2 : p.fileindex:=(getbyte shl 16) or getword;
  121. 3 : p.fileindex:=getlongint;
  122. end;
  123. case ((info shr 2) and $03) of
  124. 0 : p.line:=getbyte;
  125. 1 : p.line:=getword;
  126. 2 : p.line:=(getbyte shl 16) or getword;
  127. 3 : p.line:=getlongint;
  128. end;
  129. case ((info shr 4) and $03) of
  130. 0 : p.column:=getbyte;
  131. 1 : p.column:=getword;
  132. 2 : p.column:=(getbyte shl 16) or getword;
  133. 3 : p.column:=getlongint;
  134. end;
  135. end;
  136. function tcompilerppufile.getderef : pointer;
  137. var
  138. hp,p : tderef;
  139. b : tdereftype;
  140. begin
  141. p:=nil;
  142. repeat
  143. hp:=p;
  144. b:=tdereftype(getbyte);
  145. case b of
  146. derefnil :
  147. break;
  148. derefunit,
  149. derefaktrecordindex,
  150. derefaktlocal,
  151. derefaktstaticindex :
  152. begin
  153. p:=tderef.create(b,getword);
  154. p.next:=hp;
  155. break;
  156. end;
  157. derefindex,
  158. dereflocal,
  159. derefpara,
  160. derefrecord :
  161. begin
  162. p:=tderef.create(b,getword);
  163. p.next:=hp;
  164. end;
  165. end;
  166. until false;
  167. getderef:=p;
  168. end;
  169. function tcompilerppufile.getsymlist:tsymlist;
  170. var
  171. sym : tsym;
  172. slt : tsltype;
  173. idx : longint;
  174. p : tsymlist;
  175. begin
  176. p:=tsymlist.create;
  177. p.def:=tdef(getderef);
  178. repeat
  179. slt:=tsltype(getbyte);
  180. case slt of
  181. sl_none :
  182. break;
  183. sl_call,
  184. sl_load,
  185. sl_subscript :
  186. begin
  187. sym:=tsym(getderef);
  188. p.addsym(slt,sym);
  189. end;
  190. sl_vec :
  191. begin
  192. idx:=getlongint;
  193. p.addconst(slt,idx);
  194. end;
  195. else
  196. internalerror(200110204);
  197. end;
  198. until false;
  199. getsymlist:=tsymlist(p);
  200. end;
  201. procedure tcompilerppufile.gettype(var t:ttype);
  202. begin
  203. t.def:=tdef(getderef);
  204. t.sym:=tsym(getderef);
  205. end;
  206. function tcompilerppufile.getasmsymbol:tasmsymbol;
  207. begin
  208. getasmsymbol:=tasmsymbol(pointer(getlongint));
  209. end;
  210. procedure tcompilerppufile.putposinfo(const p:tfileposinfo);
  211. var
  212. oldcrc : boolean;
  213. info : byte;
  214. begin
  215. { posinfo is not relevant for changes in PPU }
  216. oldcrc:=do_crc;
  217. do_crc:=false;
  218. {
  219. info byte layout in bits:
  220. 0-1 - amount of bytes for fileindex
  221. 2-3 - amount of bytes for line
  222. 4-5 - amount of bytes for column
  223. }
  224. info:=0;
  225. { calculate info byte }
  226. if (p.fileindex>$ff) then
  227. begin
  228. if (p.fileindex<=$ffff) then
  229. info:=info or $1
  230. else
  231. if (p.fileindex<=$ffffff) then
  232. info:=info or $2
  233. else
  234. info:=info or $3;
  235. end;
  236. if (p.line>$ff) then
  237. begin
  238. if (p.line<=$ffff) then
  239. info:=info or $4
  240. else
  241. if (p.line<=$ffffff) then
  242. info:=info or $8
  243. else
  244. info:=info or $c;
  245. end;
  246. if (p.column>$ff) then
  247. begin
  248. if (p.column<=$ffff) then
  249. info:=info or $10
  250. else
  251. if (p.column<=$ffffff) then
  252. info:=info or $20
  253. else
  254. info:=info or $30;
  255. end;
  256. { write data }
  257. putbyte(info);
  258. case (info and $03) of
  259. 0 : putbyte(p.fileindex);
  260. 1 : putword(p.fileindex);
  261. 2 : begin
  262. putbyte(p.fileindex shr 16);
  263. putword(p.fileindex and $ffff);
  264. end;
  265. 3 : putlongint(p.fileindex);
  266. end;
  267. case ((info shr 2) and $03) of
  268. 0 : putbyte(p.line);
  269. 1 : putword(p.line);
  270. 2 : begin
  271. putbyte(p.line shr 16);
  272. putword(p.line and $ffff);
  273. end;
  274. 3 : putlongint(p.line);
  275. end;
  276. case ((info shr 4) and $03) of
  277. 0 : putbyte(p.column);
  278. 1 : putword(p.column);
  279. 2 : begin
  280. putbyte(p.column shr 16);
  281. putword(p.column and $ffff);
  282. end;
  283. 3 : putlongint(p.column);
  284. end;
  285. do_crc:=oldcrc;
  286. end;
  287. procedure tcompilerppufile.putguid(const g: tguid);
  288. begin
  289. putdata(g,sizeof(g));
  290. end;
  291. procedure tcompilerppufile.putexprint(v:tconstexprint);
  292. begin
  293. if sizeof(TConstExprInt)=8 then
  294. begin
  295. putlongint(longint(lo(v)));
  296. putlongint(longint(hi(v)));
  297. end
  298. else
  299. putlongint(v);
  300. end;
  301. procedure tcompilerppufile.PutPtrUInt(v:TConstPtrUInt);
  302. begin
  303. if sizeof(TConstPtrUInt)=8 then
  304. begin
  305. putlongint(longint(lo(v)));
  306. putlongint(longint(hi(v)));
  307. end
  308. else
  309. putlongint(v);
  310. end;
  311. procedure tcompilerppufile.putderef(p : tsymtableentry);
  312. begin
  313. if p=nil then
  314. putbyte(ord(derefnil))
  315. else
  316. begin
  317. { Static symtable ? }
  318. if p.owner.symtabletype=staticsymtable then
  319. begin
  320. putbyte(ord(derefaktstaticindex));
  321. putword(p.indexnr);
  322. end
  323. { Local record/object symtable ? }
  324. else if (p.owner=aktrecordsymtable) then
  325. begin
  326. putbyte(ord(derefaktrecordindex));
  327. putword(p.indexnr);
  328. end
  329. { Local local/para symtable ? }
  330. else if (p.owner=aktlocalsymtable) then
  331. begin
  332. putbyte(ord(derefaktlocal));
  333. putword(p.indexnr);
  334. end
  335. else
  336. begin
  337. putbyte(ord(derefindex));
  338. putword(p.indexnr);
  339. { Current unit symtable ? }
  340. repeat
  341. if not assigned(p) then
  342. internalerror(556655);
  343. case p.owner.symtabletype of
  344. { when writing the pseudo PPU file
  345. to get CRC values the globalsymtable is not yet
  346. a unitsymtable PM }
  347. globalsymtable :
  348. begin
  349. { check if the unit is available in the uses
  350. clause, else it's an error }
  351. if p.owner.unitid=$ffff then
  352. internalerror(55665566);
  353. putbyte(ord(derefunit));
  354. putword(p.owner.unitid);
  355. break;
  356. end;
  357. staticsymtable :
  358. begin
  359. putbyte(ord(derefaktstaticindex));
  360. putword(p.indexnr);
  361. break;
  362. end;
  363. localsymtable :
  364. begin
  365. p:=p.owner.defowner;
  366. putbyte(ord(dereflocal));
  367. putword(p.indexnr);
  368. end;
  369. parasymtable :
  370. begin
  371. p:=p.owner.defowner;
  372. putbyte(ord(derefpara));
  373. putword(p.indexnr);
  374. end;
  375. objectsymtable,
  376. recordsymtable :
  377. begin
  378. p:=p.owner.defowner;
  379. putbyte(ord(derefrecord));
  380. putword(p.indexnr);
  381. end;
  382. else
  383. internalerror(556656);
  384. end;
  385. until false;
  386. end;
  387. end;
  388. end;
  389. procedure tcompilerppufile.putsymlist(p:tsymlist);
  390. var
  391. hp : psymlistitem;
  392. begin
  393. putderef(p.def);
  394. hp:=p.firstsym;
  395. while assigned(hp) do
  396. begin
  397. putbyte(byte(hp^.sltype));
  398. case hp^.sltype of
  399. sl_call,
  400. sl_load,
  401. sl_subscript :
  402. putderef(hp^.sym);
  403. sl_vec :
  404. putlongint(hp^.value);
  405. else
  406. internalerror(200110205);
  407. end;
  408. hp:=hp^.next;
  409. end;
  410. putbyte(byte(sl_none));
  411. end;
  412. procedure tcompilerppufile.puttype(const t:ttype);
  413. begin
  414. { Don't write symbol references for the current unit
  415. and for the system unit }
  416. if assigned(t.sym) and
  417. (t.sym.owner.unitid<>0) and
  418. (t.sym.owner.unitid<>1) then
  419. begin
  420. putderef(nil);
  421. putderef(t.sym);
  422. end
  423. else
  424. begin
  425. putderef(t.def);
  426. putderef(nil);
  427. end;
  428. end;
  429. procedure tcompilerppufile.putasmsymbol(s:tasmsymbol);
  430. begin
  431. if assigned(s) then
  432. begin
  433. if s.ppuidx=-1 then
  434. begin
  435. inc(objectlibrary.asmsymbolppuidx);
  436. s.ppuidx:=objectlibrary.asmsymbolppuidx;
  437. end;
  438. putlongint(s.ppuidx);
  439. end
  440. else
  441. putlongint(0);
  442. end;
  443. end.
  444. {
  445. $Log$
  446. Revision 1.15 2002-08-18 20:06:26 peter
  447. * inlining is now also allowed in interface
  448. * renamed write/load to ppuwrite/ppuload
  449. * tnode storing in ppu
  450. * nld,ncon,nbas are already updated for storing in ppu
  451. Revision 1.14 2002/08/11 14:32:28 peter
  452. * renamed current_library to objectlibrary
  453. Revision 1.13 2002/08/11 13:24:14 peter
  454. * saving of asmsymbols in ppu supported
  455. * asmsymbollist global is removed and moved into a new class
  456. tasmlibrarydata that will hold the info of a .a file which
  457. corresponds with a single module. Added librarydata to tmodule
  458. to keep the library info stored for the module. In the future the
  459. objectfiles will also be stored to the tasmlibrarydata class
  460. * all getlabel/newasmsymbol and friends are moved to the new class
  461. Revision 1.12 2002/05/18 13:34:18 peter
  462. * readded missing revisions
  463. Revision 1.11 2002/05/16 19:46:45 carl
  464. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  465. + try to fix temp allocation (still in ifdef)
  466. + generic constructor calls
  467. + start of tassembler / tmodulebase class cleanup
  468. Revision 1.9 2002/05/12 16:53:15 peter
  469. * moved entry and exitcode to ncgutil and cgobj
  470. * foreach gets extra argument for passing local data to the
  471. iterator function
  472. * -CR checks also class typecasts at runtime by changing them
  473. into as
  474. * fixed compiler to cycle with the -CR option
  475. * fixed stabs with elf writer, finally the global variables can
  476. be watched
  477. * removed a lot of routines from cga unit and replaced them by
  478. calls to cgobj
  479. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  480. u32bit then the other is typecasted also to u32bit without giving
  481. a rangecheck warning/error.
  482. * fixed pascal calling method with reversing also the high tree in
  483. the parast, detected by tcalcst3 test
  484. Revision 1.8 2002/04/19 15:40:40 peter
  485. * optimize tfileposinfo writing, this reduces the ppu size with 20%
  486. }