fmodule.pas 20 KB

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