fmodule.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements the first loading and searching of the modules
  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 fmodule;
  19. {$i fpcdefs.inc}
  20. {$ifdef go32v2}
  21. {$define shortasmprefix}
  22. {$endif}
  23. {$ifdef tos}
  24. {$define shortasmprefix}
  25. {$endif}
  26. {$ifdef OS2}
  27. { Allthough OS/2 supports long filenames I play it safe and
  28. use 8.3 filenames, because this allows the compiler to run
  29. on a FAT partition. (DM) }
  30. {$define shortasmprefix}
  31. {$endif}
  32. interface
  33. uses
  34. cutils,cclasses,
  35. globals,finput,
  36. symbase,aasmbase;
  37. type
  38. trecompile_reason = (rr_unknown,
  39. rr_noppu,rr_sourcenewer,rr_build,rr_crcchanged
  40. );
  41. TExternalsItem=class(TLinkedListItem)
  42. public
  43. found : longbool;
  44. data : pstring;
  45. constructor Create(const s:string);
  46. Destructor Destroy;override;
  47. end;
  48. tlinkcontaineritem=class(tlinkedlistitem)
  49. public
  50. data : pstring;
  51. needlink : cardinal;
  52. constructor Create(const s:string;m:cardinal);
  53. destructor Destroy;override;
  54. end;
  55. tlinkcontainer=class(tlinkedlist)
  56. procedure add(const s : string;m:cardinal);
  57. function get(var m:cardinal) : string;
  58. function getusemask(mask:cardinal) : string;
  59. function find(const s:string):boolean;
  60. end;
  61. tmodule = class;
  62. tused_unit = class;
  63. tunitmap = array[0..maxunits-1] of tmodule;
  64. punitmap = ^tunitmap;
  65. tmodule = class(tmodulebase)
  66. do_reload, { force reloading of the unit }
  67. do_compile, { need to compile the sources }
  68. sources_avail, { if all sources are reachable }
  69. is_unit,
  70. in_interface, { processing the implementation part? }
  71. in_global : boolean; { allow global settings }
  72. recompile_reason : trecompile_reason; { the reason why the unit should be recompiled }
  73. crc,
  74. interface_crc : cardinal;
  75. flags : cardinal; { the PPU flags }
  76. islibrary : boolean; { if it is a library (win32 dll) }
  77. map : punitmap; { mapping of all used units }
  78. unitcount : longint; { local unit counter }
  79. globalsymtable, { pointer to the global symtable of this unit }
  80. localsymtable : tsymtable;{ pointer to the local symtable of this unit }
  81. scanner : pointer; { scanner object used }
  82. procinfo : pointer; { current procedure being compiled }
  83. loaded_from : tmodule;
  84. uses_imports : boolean; { Set if the module imports from DLL's.}
  85. imports : tlinkedlist;
  86. _exports : tlinkedlist;
  87. externals : tlinkedlist; {Only for DLL scanners by using Unix-style $LINKLIB }
  88. resourcefiles : tstringlist;
  89. linkunitofiles,
  90. linkunitstaticlibs,
  91. linkunitsharedlibs,
  92. linkotherofiles, { objects,libs loaded from the source }
  93. linkothersharedlibs, { using $L or $LINKLIB or import lib (for linux) }
  94. linkotherstaticlibs : tlinkcontainer;
  95. used_units : tlinkedlist;
  96. dependent_units : tlinkedlist;
  97. localunitsearchpath, { local searchpaths }
  98. localobjectsearchpath,
  99. localincludesearchpath,
  100. locallibrarysearchpath : TSearchPathList;
  101. asmprefix : pstring; { prefix for the smartlink asmfiles }
  102. librarydata : tasmlibrarydata; { librarydata for this module }
  103. {create creates a new module which name is stored in 's'. LoadedFrom
  104. points to the module calling it. It is nil for the first compiled
  105. module. This allow inheritence of all path lists. MUST pay attention
  106. to that when creating link.res!!!!(mazen)}
  107. constructor create(LoadedFrom:TModule;const s:string;_is_unit:boolean);
  108. destructor destroy;override;
  109. procedure reset;virtual;
  110. procedure adddependency(callermodule:tmodule);
  111. procedure flagdependent(callermodule:tmodule);
  112. function addusedunit(hp:tmodule;inuses:boolean):tused_unit;
  113. procedure numberunits;
  114. end;
  115. tused_unit = class(tlinkedlistitem)
  116. unitid : longint;
  117. checksum,
  118. interface_checksum : cardinal;
  119. in_uses,
  120. in_interface,
  121. is_stab_written : boolean;
  122. u : tmodule;
  123. constructor create(_u : tmodule;intface,inuses:boolean);
  124. end;
  125. tdependent_unit = class(tlinkedlistitem)
  126. u : tmodule;
  127. constructor create(_u : tmodule);
  128. end;
  129. var
  130. main_module : tmodule; { Main module of the program }
  131. current_module : tmodule; { Current module which is compiled or loaded }
  132. compiled_module : tmodule; { Current module which is compiled }
  133. usedunits : tlinkedlist; { Used units for this program }
  134. loaded_units : tlinkedlist; { All loaded units }
  135. SmartLinkOFiles : TStringList; { List of .o files which are generated,
  136. used to delete them after linking }
  137. function get_source_file(moduleindex,fileindex : longint) : tinputfile;
  138. implementation
  139. uses
  140. {$ifdef delphi}
  141. dmisc,
  142. {$else}
  143. dos,
  144. {$endif}
  145. verbose,systems,
  146. scanner,
  147. cgbase;
  148. {*****************************************************************************
  149. Global Functions
  150. *****************************************************************************}
  151. function get_source_file(moduleindex,fileindex : longint) : tinputfile;
  152. var
  153. hp : tmodule;
  154. begin
  155. hp:=tmodule(loaded_units.first);
  156. while assigned(hp) and (hp.unit_index<>moduleindex) do
  157. hp:=tmodule(hp.next);
  158. if assigned(hp) then
  159. get_source_file:=hp.sourcefiles.get_file(fileindex)
  160. else
  161. get_source_file:=nil;
  162. end;
  163. {****************************************************************************
  164. TLinkContainerItem
  165. ****************************************************************************}
  166. constructor TLinkContainerItem.Create(const s:string;m:cardinal);
  167. begin
  168. inherited Create;
  169. data:=stringdup(s);
  170. needlink:=m;
  171. end;
  172. destructor TLinkContainerItem.Destroy;
  173. begin
  174. stringdispose(data);
  175. end;
  176. {****************************************************************************
  177. TLinkContainer
  178. ****************************************************************************}
  179. procedure TLinkContainer.add(const s : string;m:cardinal);
  180. begin
  181. inherited concat(TLinkContainerItem.Create(s,m));
  182. end;
  183. function TLinkContainer.get(var m:cardinal) : string;
  184. var
  185. p : tlinkcontaineritem;
  186. begin
  187. p:=tlinkcontaineritem(inherited getfirst);
  188. if p=nil then
  189. begin
  190. get:='';
  191. m:=0;
  192. end
  193. else
  194. begin
  195. get:=p.data^;
  196. m:=p.needlink;
  197. p.free;
  198. end;
  199. end;
  200. function TLinkContainer.getusemask(mask:cardinal) : string;
  201. var
  202. p : tlinkcontaineritem;
  203. found : boolean;
  204. begin
  205. found:=false;
  206. repeat
  207. p:=tlinkcontaineritem(inherited getfirst);
  208. if p=nil then
  209. begin
  210. getusemask:='';
  211. exit;
  212. end;
  213. getusemask:=p.data^;
  214. found:=(p.needlink and mask)<>0;
  215. p.free;
  216. until found;
  217. end;
  218. function TLinkContainer.find(const s:string):boolean;
  219. var
  220. newnode : tlinkcontaineritem;
  221. begin
  222. find:=false;
  223. newnode:=tlinkcontaineritem(First);
  224. while assigned(newnode) do
  225. begin
  226. if newnode.data^=s then
  227. begin
  228. find:=true;
  229. exit;
  230. end;
  231. newnode:=tlinkcontaineritem(newnode.next);
  232. end;
  233. end;
  234. {****************************************************************************
  235. TExternalsItem
  236. ****************************************************************************}
  237. constructor tExternalsItem.Create(const s:string);
  238. begin
  239. inherited Create;
  240. found:=false;
  241. data:=stringdup(s);
  242. end;
  243. destructor tExternalsItem.Destroy;
  244. begin
  245. stringdispose(data);
  246. inherited;
  247. end;
  248. {****************************************************************************
  249. TUSED_UNIT
  250. ****************************************************************************}
  251. constructor tused_unit.create(_u : tmodule;intface,inuses:boolean);
  252. begin
  253. u:=_u;
  254. in_interface:=intface;
  255. in_uses:=inuses;
  256. is_stab_written:=false;
  257. unitid:=0;
  258. if _u.state=ms_compiled then
  259. begin
  260. checksum:=u.crc;
  261. interface_checksum:=u.interface_crc;
  262. end
  263. else
  264. begin
  265. checksum:=0;
  266. interface_checksum:=0;
  267. end;
  268. end;
  269. {****************************************************************************
  270. TDENPENDENT_UNIT
  271. ****************************************************************************}
  272. constructor tdependent_unit.create(_u : tmodule);
  273. begin
  274. u:=_u;
  275. end;
  276. {****************************************************************************
  277. TMODULE
  278. ****************************************************************************}
  279. constructor tmodule.create(LoadedFrom:TModule;const s:string;_is_unit:boolean);
  280. var
  281. p : dirstr;
  282. n : namestr;
  283. e : extstr;
  284. begin
  285. FSplit(s,p,n,e);
  286. { Programs have the name 'Program' to don't conflict with dup id's }
  287. if _is_unit then
  288. inherited create(n)
  289. else
  290. inherited create('Program');
  291. mainsource:=stringdup(s);
  292. { Dos has the famous 8.3 limit :( }
  293. {$ifdef shortasmprefix}
  294. asmprefix:=stringdup(FixFileName('as'));
  295. {$else}
  296. asmprefix:=stringdup(FixFileName(n));
  297. {$endif}
  298. setfilename(p+n,true);
  299. localunitsearchpath:=TSearchPathList.Create;
  300. localobjectsearchpath:=TSearchPathList.Create;
  301. localincludesearchpath:=TSearchPathList.Create;
  302. locallibrarysearchpath:=TSearchPathList.Create;
  303. used_units:=TLinkedList.Create;
  304. dependent_units:=TLinkedList.Create;
  305. resourcefiles:=TStringList.Create;
  306. linkunitofiles:=TLinkContainer.Create;
  307. linkunitstaticlibs:=TLinkContainer.Create;
  308. linkunitsharedlibs:=TLinkContainer.Create;
  309. linkotherofiles:=TLinkContainer.Create;
  310. linkotherstaticlibs:=TLinkContainer.Create;
  311. linkothersharedlibs:=TLinkContainer.Create;
  312. crc:=0;
  313. interface_crc:=0;
  314. flags:=0;
  315. scanner:=nil;
  316. map:=nil;
  317. globalsymtable:=nil;
  318. localsymtable:=nil;
  319. loaded_from:=LoadedFrom;
  320. do_reload:=false;
  321. unitcount:=1;
  322. do_compile:=false;
  323. sources_avail:=true;
  324. recompile_reason:=rr_unknown;
  325. in_interface:=true;
  326. in_global:=true;
  327. is_unit:=_is_unit;
  328. islibrary:=false;
  329. uses_imports:=false;
  330. imports:=TLinkedList.Create;
  331. _exports:=TLinkedList.Create;
  332. externals:=TLinkedList.Create;
  333. librarydata:=tasmlibrarydata.create(realmodulename^);
  334. end;
  335. destructor tmodule.Destroy;
  336. var
  337. {$ifdef MEMDEBUG}
  338. d : tmemdebug;
  339. {$endif}
  340. hpi : tprocinfo;
  341. begin
  342. if assigned(map) then
  343. dispose(map);
  344. if assigned(imports) then
  345. imports.free;
  346. if assigned(_exports) then
  347. _exports.free;
  348. if assigned(externals) then
  349. externals.free;
  350. if assigned(scanner) then
  351. begin
  352. { also update current_scanner if it was pointing
  353. to this module }
  354. if current_scanner=tscannerfile(scanner) then
  355. current_scanner:=nil;
  356. tscannerfile(scanner).free;
  357. end;
  358. if assigned(procinfo) then
  359. begin
  360. if current_procinfo=tprocinfo(procinfo) then
  361. current_procinfo:=nil;
  362. { release procinfo tree }
  363. while assigned(procinfo) do
  364. begin
  365. hpi:=tprocinfo(procinfo).parent;
  366. tprocinfo(procinfo).free;
  367. procinfo:=hpi;
  368. end;
  369. end;
  370. used_units.free;
  371. dependent_units.free;
  372. resourcefiles.Free;
  373. linkunitofiles.Free;
  374. linkunitstaticlibs.Free;
  375. linkunitsharedlibs.Free;
  376. linkotherofiles.Free;
  377. linkotherstaticlibs.Free;
  378. linkothersharedlibs.Free;
  379. stringdispose(objfilename);
  380. stringdispose(newfilename);
  381. stringdispose(ppufilename);
  382. stringdispose(staticlibfilename);
  383. stringdispose(sharedlibfilename);
  384. stringdispose(exefilename);
  385. stringdispose(outputpath);
  386. stringdispose(path);
  387. stringdispose(realmodulename);
  388. stringdispose(mainsource);
  389. stringdispose(asmprefix);
  390. localunitsearchpath.Free;
  391. localobjectsearchpath.free;
  392. localincludesearchpath.free;
  393. locallibrarysearchpath.free;
  394. {$ifdef MEMDEBUG}
  395. d:=tmemdebug.create(modulename^+' - symtable');
  396. {$endif}
  397. if assigned(globalsymtable) then
  398. globalsymtable.free;
  399. if assigned(localsymtable) then
  400. localsymtable.free;
  401. {$ifdef MEMDEBUG}
  402. d.free;
  403. {$endif}
  404. {$ifdef MEMDEBUG}
  405. d:=tmemdebug.create(modulename^+' - librarydata');
  406. {$endif}
  407. librarydata.free;
  408. {$ifdef MEMDEBUG}
  409. d.free;
  410. {$endif}
  411. stringdispose(modulename);
  412. inherited Destroy;
  413. end;
  414. procedure tmodule.reset;
  415. var
  416. hpi : tprocinfo;
  417. begin
  418. if assigned(scanner) then
  419. begin
  420. { also update current_scanner if it was pointing
  421. to this module }
  422. if current_scanner=tscannerfile(scanner) then
  423. current_scanner:=nil;
  424. tscannerfile(scanner).free;
  425. scanner:=nil;
  426. end;
  427. if assigned(procinfo) then
  428. begin
  429. if current_procinfo=tprocinfo(procinfo) then
  430. current_procinfo:=nil;
  431. { release procinfo tree }
  432. while assigned(procinfo) do
  433. begin
  434. hpi:=tprocinfo(procinfo).parent;
  435. tprocinfo(procinfo).free;
  436. procinfo:=hpi;
  437. end;
  438. end;
  439. if assigned(globalsymtable) then
  440. begin
  441. globalsymtable.free;
  442. globalsymtable:=nil;
  443. end;
  444. if assigned(localsymtable) then
  445. begin
  446. localsymtable.free;
  447. localsymtable:=nil;
  448. end;
  449. if assigned(map) then
  450. begin
  451. dispose(map);
  452. map:=nil;
  453. end;
  454. sourcefiles.free;
  455. sourcefiles:=tinputfilemanager.create;
  456. librarydata.free;
  457. librarydata:=tasmlibrarydata.create(realmodulename^);
  458. imports.free;
  459. imports:=tlinkedlist.create;
  460. _exports.free;
  461. _exports:=tlinkedlist.create;
  462. externals.free;
  463. externals:=tlinkedlist.create;
  464. used_units.free;
  465. used_units:=TLinkedList.Create;
  466. dependent_units.free;
  467. dependent_units:=TLinkedList.Create;
  468. resourcefiles.Free;
  469. resourcefiles:=TStringList.Create;
  470. linkunitofiles.Free;
  471. linkunitofiles:=TLinkContainer.Create;
  472. linkunitstaticlibs.Free;
  473. linkunitstaticlibs:=TLinkContainer.Create;
  474. linkunitsharedlibs.Free;
  475. linkunitsharedlibs:=TLinkContainer.Create;
  476. linkotherofiles.Free;
  477. linkotherofiles:=TLinkContainer.Create;
  478. linkotherstaticlibs.Free;
  479. linkotherstaticlibs:=TLinkContainer.Create;
  480. linkothersharedlibs.Free;
  481. linkothersharedlibs:=TLinkContainer.Create;
  482. uses_imports:=false;
  483. do_compile:=false;
  484. in_interface:=true;
  485. in_global:=true;
  486. crc:=0;
  487. interface_crc:=0;
  488. flags:=0;
  489. unitcount:=1;
  490. recompile_reason:=rr_unknown;
  491. {
  492. The following fields should not
  493. be reset:
  494. mainsource
  495. loaded_from
  496. state
  497. sources_avail
  498. }
  499. end;
  500. procedure tmodule.adddependency(callermodule:tmodule);
  501. begin
  502. { This is not needed for programs }
  503. if not callermodule.is_unit then
  504. exit;
  505. Comment(V_Used,'Add dependency for '+callermodule.modulename^+' to '+modulename^);
  506. dependent_units.concat(tdependent_unit.create(callermodule));
  507. end;
  508. procedure tmodule.flagdependent(callermodule:tmodule);
  509. var
  510. pm : tdependent_unit;
  511. begin
  512. { flag all units that depend on this unit for reloading }
  513. pm:=tdependent_unit(current_module.dependent_units.first);
  514. while assigned(pm) do
  515. begin
  516. { We do not have to reload the unit that wants to load
  517. this unit }
  518. if pm.u=callermodule then
  519. Comment(v_used,'No reload, is caller: '+pm.u.modulename^)
  520. else
  521. if pm.u.state=ms_second_compile then
  522. Comment(v_used,'No reload, already in second compile: '+pm.u.modulename^)
  523. else
  524. begin
  525. pm.u.do_reload:=true;
  526. Comment(v_used,'Flag for reload '+pm.u.modulename^);
  527. end;
  528. pm:=tdependent_unit(pm.next);
  529. end;
  530. end;
  531. function tmodule.addusedunit(hp:tmodule;inuses:boolean):tused_unit;
  532. var
  533. pu : tused_unit;
  534. begin
  535. pu:=tused_unit.create(hp,in_interface,inuses);
  536. used_units.concat(pu);
  537. addusedunit:=pu;
  538. end;
  539. procedure tmodule.numberunits;
  540. var
  541. counter : word;
  542. hp : tused_unit;
  543. hp1 : tmodule;
  544. begin
  545. { Reset all numbers to -1 }
  546. hp1:=tmodule(loaded_units.first);
  547. while assigned(hp1) do
  548. begin
  549. if assigned(hp1.globalsymtable) then
  550. hp1.globalsymtable.unitid:=$ffff;
  551. hp1:=tmodule(hp1.next);
  552. end;
  553. { Our own symtable gets unitid 0, for a program there is
  554. no globalsymtable }
  555. if assigned(globalsymtable) then
  556. globalsymtable.unitid:=0;
  557. { number units }
  558. counter:=1;
  559. hp:=tused_unit(used_units.first);
  560. while assigned(hp) do
  561. begin
  562. tsymtable(hp.u.globalsymtable).unitid:=counter;
  563. inc(counter);
  564. hp:=tused_unit(hp.next);
  565. end;
  566. end;
  567. end.
  568. {
  569. $Log$
  570. Revision 1.33 2003-04-27 11:21:32 peter
  571. * aktprocdef renamed to current_procdef
  572. * procinfo renamed to current_procinfo
  573. * procinfo will now be stored in current_module so it can be
  574. cleaned up properly
  575. * gen_main_procsym changed to create_main_proc and release_main_proc
  576. to also generate a tprocinfo structure
  577. * fixed unit implicit initfinal
  578. Revision 1.32 2002/12/29 14:57:50 peter
  579. * unit loading changed to first register units and load them
  580. afterwards. This is needed to support uses xxx in yyy correctly
  581. * unit dependency check fixed
  582. Revision 1.31 2002/12/07 14:27:07 carl
  583. * 3% memory optimization
  584. * changed some types
  585. + added type checking with different size for call node and for
  586. parameters
  587. Revision 1.30 2002/11/24 18:19:56 carl
  588. + tos also has short filenames
  589. Revision 1.29 2002/11/20 12:36:23 mazen
  590. * $UNITPATH directive is now working
  591. Revision 1.28 2002/09/05 19:29:42 peter
  592. * memdebug enhancements
  593. Revision 1.27 2002/08/16 15:31:08 peter
  594. * fixed possible crashes with current_scanner
  595. Revision 1.26 2002/08/12 16:46:04 peter
  596. * tscannerfile is now destroyed in tmodule.reset and current_scanner
  597. is updated accordingly. This removes all the loading and saving of
  598. the old scanner and the invalid flag marking
  599. Revision 1.25 2002/08/11 14:28:19 peter
  600. * TScannerFile.SetInvalid added that will also reset inputfile
  601. Revision 1.24 2002/08/11 13:24:11 peter
  602. * saving of asmsymbols in ppu supported
  603. * asmsymbollist global is removed and moved into a new class
  604. tasmlibrarydata that will hold the info of a .a file which
  605. corresponds with a single module. Added librarydata to tmodule
  606. to keep the library info stored for the module. In the future the
  607. objectfiles will also be stored to the tasmlibrarydata class
  608. * all getlabel/newasmsymbol and friends are moved to the new class
  609. Revision 1.23 2002/05/16 19:46:36 carl
  610. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  611. + try to fix temp allocation (still in ifdef)
  612. + generic constructor calls
  613. + start of tassembler / tmodulebase class cleanup
  614. Revision 1.22 2002/05/14 19:34:41 peter
  615. * removed old logs and updated copyright year
  616. Revision 1.21 2002/04/04 19:05:55 peter
  617. * removed unused units
  618. * use tlocation.size in cg.a_*loc*() routines
  619. Revision 1.20 2002/03/28 20:46:59 carl
  620. - remove go32v1 support
  621. }