symppu.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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 if sizeof(TConstExprInt)=4 then
  299. putlongint(longint(v))
  300. else
  301. internalerror(2002082601);
  302. end;
  303. procedure tcompilerppufile.PutPtrUInt(v:TConstPtrUInt);
  304. begin
  305. if sizeof(TConstPtrUInt)=8 then
  306. begin
  307. putlongint(longint(lo(v)));
  308. putlongint(longint(hi(v)));
  309. end
  310. else if sizeof(TConstPtrUInt)=4 then
  311. putlongint(longint(v))
  312. else
  313. internalerror(2002082601);
  314. end;
  315. procedure tcompilerppufile.putderef(p : tsymtableentry);
  316. begin
  317. if p=nil then
  318. putbyte(ord(derefnil))
  319. else
  320. begin
  321. { Static symtable ? }
  322. if p.owner.symtabletype=staticsymtable then
  323. begin
  324. putbyte(ord(derefaktstaticindex));
  325. putword(p.indexnr);
  326. end
  327. { Local record/object symtable ? }
  328. else if (p.owner=aktrecordsymtable) then
  329. begin
  330. putbyte(ord(derefaktrecordindex));
  331. putword(p.indexnr);
  332. end
  333. { Local local/para symtable ? }
  334. else if (p.owner=aktlocalsymtable) then
  335. begin
  336. putbyte(ord(derefaktlocal));
  337. putword(p.indexnr);
  338. end
  339. else
  340. begin
  341. putbyte(ord(derefindex));
  342. putword(p.indexnr);
  343. { Current unit symtable ? }
  344. repeat
  345. if not assigned(p) then
  346. internalerror(556655);
  347. case p.owner.symtabletype of
  348. { when writing the pseudo PPU file
  349. to get CRC values the globalsymtable is not yet
  350. a unitsymtable PM }
  351. globalsymtable :
  352. begin
  353. { check if the unit is available in the uses
  354. clause, else it's an error }
  355. if p.owner.unitid=$ffff then
  356. internalerror(55665566);
  357. putbyte(ord(derefunit));
  358. putword(p.owner.unitid);
  359. break;
  360. end;
  361. staticsymtable :
  362. begin
  363. putbyte(ord(derefaktstaticindex));
  364. putword(p.indexnr);
  365. break;
  366. end;
  367. localsymtable :
  368. begin
  369. p:=p.owner.defowner;
  370. putbyte(ord(dereflocal));
  371. putword(p.indexnr);
  372. end;
  373. parasymtable :
  374. begin
  375. p:=p.owner.defowner;
  376. putbyte(ord(derefpara));
  377. putword(p.indexnr);
  378. end;
  379. objectsymtable,
  380. recordsymtable :
  381. begin
  382. p:=p.owner.defowner;
  383. putbyte(ord(derefrecord));
  384. putword(p.indexnr);
  385. end;
  386. else
  387. internalerror(556656);
  388. end;
  389. until false;
  390. end;
  391. end;
  392. end;
  393. procedure tcompilerppufile.putsymlist(p:tsymlist);
  394. var
  395. hp : psymlistitem;
  396. begin
  397. putderef(p.def);
  398. hp:=p.firstsym;
  399. while assigned(hp) do
  400. begin
  401. putbyte(byte(hp^.sltype));
  402. case hp^.sltype of
  403. sl_call,
  404. sl_load,
  405. sl_subscript :
  406. putderef(hp^.sym);
  407. sl_vec :
  408. putlongint(hp^.value);
  409. else
  410. internalerror(200110205);
  411. end;
  412. hp:=hp^.next;
  413. end;
  414. putbyte(byte(sl_none));
  415. end;
  416. procedure tcompilerppufile.puttype(const t:ttype);
  417. begin
  418. { Don't write symbol references for the current unit
  419. and for the system unit }
  420. if assigned(t.sym) and
  421. (t.sym.owner.unitid<>0) and
  422. (t.sym.owner.unitid<>1) then
  423. begin
  424. putderef(nil);
  425. putderef(t.sym);
  426. end
  427. else
  428. begin
  429. putderef(t.def);
  430. putderef(nil);
  431. end;
  432. end;
  433. procedure tcompilerppufile.putasmsymbol(s:tasmsymbol);
  434. begin
  435. if assigned(s) then
  436. begin
  437. if s.ppuidx=-1 then
  438. begin
  439. inc(objectlibrary.asmsymbolppuidx);
  440. s.ppuidx:=objectlibrary.asmsymbolppuidx;
  441. end;
  442. putlongint(s.ppuidx);
  443. end
  444. else
  445. putlongint(0);
  446. end;
  447. end.
  448. {
  449. $Log$
  450. Revision 1.16 2002-08-26 14:05:57 pierre
  451. * fixed compilation cycle with -Cr option by adding explicit
  452. longint typecast in PutPtrUInt and putexprint methods.
  453. + added checks for sizeof and internalerros if size is not handled.
  454. Revision 1.15 2002/08/18 20:06:26 peter
  455. * inlining is now also allowed in interface
  456. * renamed write/load to ppuwrite/ppuload
  457. * tnode storing in ppu
  458. * nld,ncon,nbas are already updated for storing in ppu
  459. Revision 1.14 2002/08/11 14:32:28 peter
  460. * renamed current_library to objectlibrary
  461. Revision 1.13 2002/08/11 13:24:14 peter
  462. * saving of asmsymbols in ppu supported
  463. * asmsymbollist global is removed and moved into a new class
  464. tasmlibrarydata that will hold the info of a .a file which
  465. corresponds with a single module. Added librarydata to tmodule
  466. to keep the library info stored for the module. In the future the
  467. objectfiles will also be stored to the tasmlibrarydata class
  468. * all getlabel/newasmsymbol and friends are moved to the new class
  469. Revision 1.12 2002/05/18 13:34:18 peter
  470. * readded missing revisions
  471. Revision 1.11 2002/05/16 19:46:45 carl
  472. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  473. + try to fix temp allocation (still in ifdef)
  474. + generic constructor calls
  475. + start of tassembler / tmodulebase class cleanup
  476. Revision 1.9 2002/05/12 16:53:15 peter
  477. * moved entry and exitcode to ncgutil and cgobj
  478. * foreach gets extra argument for passing local data to the
  479. iterator function
  480. * -CR checks also class typecasts at runtime by changing them
  481. into as
  482. * fixed compiler to cycle with the -CR option
  483. * fixed stabs with elf writer, finally the global variables can
  484. be watched
  485. * removed a lot of routines from cga unit and replaced them by
  486. calls to cgobj
  487. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  488. u32bit then the other is typecasted also to u32bit without giving
  489. a rangecheck warning/error.
  490. * fixed pascal calling method with reversing also the high tree in
  491. the parast, detected by tcalcst3 test
  492. Revision 1.8 2002/04/19 15:40:40 peter
  493. * optimize tfileposinfo writing, this reduces the ppu size with 20%
  494. }