fppu.pas 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the first loading and searching of the modules
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit fppu;
  18. {$i fpcdefs.inc}
  19. { $define DEBUG_UNIT_CRC_CHANGES}
  20. { close ppufiles on system that are
  21. short on file handles like DOS system PM }
  22. {$ifdef GO32V2}
  23. {$define SHORT_ON_FILE_HANDLES}
  24. {$endif GO32V2}
  25. {$ifdef WATCOM}
  26. {$define SHORT_ON_FILE_HANDLES}
  27. {$endif WATCOM}
  28. interface
  29. uses
  30. cmsgs,verbose,
  31. cutils,cclasses,cstreams,
  32. globtype,globals,finput,fmodule,
  33. symbase,ppu,symtype;
  34. type
  35. { tppumodule }
  36. tppumodule = class(tmodule)
  37. ppufile : tcompilerppufile; { the PPU file }
  38. sourcefn : TPathStr; { Source specified with "uses .. in '..'" }
  39. comments : TCmdStrList;
  40. nsprefix : TCmdStr; { Namespace prefix the unit was found with }
  41. {$ifdef Test_Double_checksum}
  42. crc_array : pointer;
  43. crc_size : longint;
  44. crc_array2 : pointer;
  45. crc_size2 : longint;
  46. {$endif def Test_Double_checksum}
  47. constructor create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
  48. destructor destroy;override;
  49. procedure reset;override;
  50. function openppufile:boolean;
  51. function openppustream(strm:TCStream):boolean;
  52. procedure getppucrc;
  53. procedure writeppu;
  54. procedure loadppu;
  55. function needrecompile:boolean;
  56. procedure setdefgeneration;
  57. procedure reload_flagged_units;
  58. procedure end_of_parsing;override;
  59. private
  60. unitimportsymsderefs : tfplist;
  61. { Each time a unit's defs are (re)created, its defsgeneration is
  62. set to the value of a global counter, and the global counter is
  63. increased. We only reresolve its dependent units' defs in case
  64. they have been resolved only for an older generation, in order to
  65. avoid endless resolving loops in case of cyclic dependencies. }
  66. defsgeneration : longint;
  67. function openppu(ppufiletime:longint):boolean;
  68. function search_unit_files(onlysource:boolean):boolean;
  69. function search_unit(onlysource,shortname:boolean):boolean;
  70. function loadfrompackage:boolean;
  71. procedure load_interface;
  72. procedure load_implementation;
  73. procedure load_usedunits;
  74. procedure printcomments;
  75. procedure queuecomment(const s:TMsgStr;v,w:longint);
  76. procedure buildderefunitimportsyms;
  77. procedure derefunitimportsyms;
  78. procedure freederefunitimportsyms;
  79. procedure writesourcefiles;
  80. procedure writeusedunit(intf:boolean);
  81. procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  82. procedure writederefmap;
  83. procedure writederefdata;
  84. procedure writeImportSymbols;
  85. procedure writeResources;
  86. procedure writeOrderedSymbols;
  87. procedure writeunitimportsyms;
  88. procedure writeasmsyms(kind:tunitasmlisttype;list:tfphashobjectlist);
  89. procedure writeextraheader;
  90. procedure readsourcefiles;
  91. procedure readloadunit;
  92. procedure readlinkcontainer(var p:tlinkcontainer);
  93. procedure readderefmap;
  94. procedure readderefdata;
  95. procedure readImportSymbols;
  96. procedure readResources;
  97. procedure readOrderedSymbols;
  98. procedure readwpofile;
  99. procedure readunitimportsyms;
  100. procedure readasmsyms;
  101. procedure readextraheader;
  102. {$IFDEF MACRO_DIFF_HINT}
  103. procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
  104. procedure writeusedmacros;
  105. procedure readusedmacros;
  106. {$ENDIF}
  107. end;
  108. function registerunit(callermodule:tmodule;const s : TIDString;const fn:string) : tppumodule;
  109. implementation
  110. uses
  111. SysUtils,
  112. cfileutl,
  113. systems,version,options,
  114. symtable, symsym,
  115. wpoinfo,
  116. scanner,
  117. aasmbase,ogbase,
  118. parser,
  119. comphook,
  120. entfile,fpkg,fpcp;
  121. var
  122. currentdefgeneration: longint;
  123. {****************************************************************************
  124. TPPUMODULE
  125. ****************************************************************************}
  126. constructor tppumodule.create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
  127. begin
  128. inherited create(LoadedFrom,amodulename,afilename,_is_unit);
  129. ppufile:=nil;
  130. sourcefn:=afilename;
  131. unitimportsymsderefs:=tfplist.create;
  132. end;
  133. destructor tppumodule.Destroy;
  134. begin
  135. if assigned(ppufile) then
  136. ppufile.free;
  137. ppufile:=nil;
  138. comments.free;
  139. comments:=nil;
  140. { all derefs allocated with new
  141. are dispose'd inside this method }
  142. freederefunitimportsyms;
  143. unitimportsymsderefs.free;
  144. unitimportsymsderefs:=nil;
  145. inherited Destroy;
  146. end;
  147. procedure tppumodule.reset;
  148. begin
  149. inc(currentdefgeneration);
  150. if assigned(ppufile) then
  151. begin
  152. ppufile.free;
  153. ppufile:=nil;
  154. end;
  155. freederefunitimportsyms;
  156. unitimportsymsderefs.free;
  157. unitimportsymsderefs:=tfplist.create;
  158. inherited reset;
  159. end;
  160. procedure tppumodule.queuecomment(const s:TMsgStr;v,w:longint);
  161. begin
  162. if comments = nil then
  163. comments := TCmdStrList.create;
  164. comments.insert(s);
  165. end;
  166. procedure tppumodule.printcomments;
  167. var
  168. comment: string;
  169. begin
  170. if comments = nil then
  171. exit;
  172. { comments are inserted in reverse order }
  173. repeat
  174. comment := comments.getlast;
  175. if length(comment) = 0 then
  176. exit;
  177. do_comment(v_normal, comment);
  178. until false;
  179. end;
  180. function tppumodule.openppufile:boolean;
  181. var
  182. ppufiletime : longint;
  183. begin
  184. openppufile:=false;
  185. Message1(unit_t_ppu_loading,ppufilename,@queuecomment);
  186. { Get ppufile time (also check if the file exists) }
  187. ppufiletime:=getnamedfiletime(ppufilename);
  188. if ppufiletime=-1 then
  189. exit;
  190. { Open the ppufile }
  191. Message1(unit_u_ppu_name,ppufilename);
  192. ppufile:=tcompilerppufile.create(ppufilename);
  193. if not ppufile.openfile then
  194. begin
  195. ppufile.free;
  196. ppufile:=nil;
  197. Message(unit_u_ppu_file_too_short);
  198. exit;
  199. end;
  200. result:=openppu(ppufiletime);
  201. end;
  202. function tppumodule.openppustream(strm:TCStream):boolean;
  203. begin
  204. result:=false;
  205. { Open the ppufile }
  206. Message1(unit_u_ppu_name,ppufilename);
  207. ppufile:=tcompilerppufile.create(ppufilename);
  208. if not ppufile.openstream(strm) then
  209. begin
  210. ppufile.free;
  211. ppufile:=nil;
  212. Message(unit_u_ppu_file_too_short);
  213. exit;
  214. end;
  215. result:=openppu(-1);
  216. end;
  217. function tppumodule.openppu(ppufiletime:longint):boolean;
  218. function checkheader: boolean;
  219. begin
  220. result:=false;
  221. { check for a valid PPU file }
  222. if not ppufile.CheckPPUId then
  223. begin
  224. Message(unit_u_ppu_invalid_header);
  225. exit;
  226. end;
  227. { check for allowed PPU versions }
  228. if not (ppufile.getversion = CurrentPPUVersion) then
  229. begin
  230. Message1(unit_u_ppu_invalid_version,tostr(ppufile.getversion),@queuecomment);
  231. exit;
  232. end;
  233. { check the target processor }
  234. if tsystemcpu(ppufile.header.common.cpu)<>target_cpu then
  235. begin
  236. Message(unit_u_ppu_invalid_processor,@queuecomment);
  237. exit;
  238. end;
  239. { check target }
  240. if tsystem(ppufile.header.common.target)<>target_info.system then
  241. begin
  242. Message(unit_u_ppu_invalid_target,@queuecomment);
  243. exit;
  244. end;
  245. {$ifdef cpufpemu}
  246. { check if floating point emulation is on?
  247. fpu emulation isn't unit levelwise because it affects calling convention }
  248. if ((ppufile.header.common.flags and uf_fpu_emulation)<>0) <>
  249. (cs_fp_emulation in current_settings.moduleswitches) then
  250. begin
  251. Message(unit_u_ppu_invalid_fpumode,@queuecomment);
  252. exit;
  253. end;
  254. {$endif cpufpemu}
  255. result:=true;
  256. end;
  257. function checkextraheader: boolean;
  258. begin
  259. result:=false;
  260. if ppufile.readentry<>ibextraheader then
  261. begin
  262. Message(unit_u_ppu_invalid_header);
  263. exit;
  264. end;
  265. readextraheader;
  266. if (longversion<>CurrentPPULongVersion) or
  267. not ppufile.EndOfEntry then
  268. begin
  269. Message(unit_u_ppu_invalid_header);
  270. exit;
  271. end;
  272. {$ifdef i8086}
  273. { check i8086 memory model flags }
  274. if (mf_i8086_far_code in moduleflags) <>
  275. (current_settings.x86memorymodel in [mm_medium,mm_large,mm_huge]) then
  276. begin
  277. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  278. exit;
  279. end;
  280. if (mf_i8086_far_data in moduleflags) <>
  281. (current_settings.x86memorymodel in [mm_compact,mm_large]) then
  282. begin
  283. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  284. exit;
  285. end;
  286. if (mf_i8086_huge_data in moduleflags) <>
  287. (current_settings.x86memorymodel=mm_huge) then
  288. begin
  289. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  290. exit;
  291. end;
  292. if (mf_i8086_cs_equals_ds in moduleflags) <>
  293. (current_settings.x86memorymodel=mm_tiny) then
  294. begin
  295. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  296. exit;
  297. end;
  298. if (mf_i8086_ss_equals_ds in moduleflags) <>
  299. (current_settings.x86memorymodel in [mm_tiny,mm_small,mm_medium]) then
  300. begin
  301. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  302. exit;
  303. end;
  304. {$endif i8086}
  305. if {$ifdef llvm}not{$endif}(mf_llvm in moduleflags) then
  306. begin
  307. Message(unit_u_ppu_llvm_mismatch,@queuecomment);
  308. exit;
  309. end;
  310. result:=true;
  311. end;
  312. begin
  313. openppu:=false;
  314. if not checkheader or
  315. not checkextraheader then
  316. begin
  317. ppufile.free;
  318. ppufile:=nil;
  319. exit;
  320. end;
  321. { Load values to be access easier }
  322. headerflags:=ppufile.header.common.flags;
  323. crc:=ppufile.header.checksum;
  324. interface_crc:=ppufile.header.interface_checksum;
  325. indirect_crc:=ppufile.header.indirect_checksum;
  326. { Show Debug info }
  327. if ppufiletime<>-1 then
  328. Message1(unit_u_ppu_time,filetimestring(ppufiletime))
  329. else
  330. Message1(unit_u_ppu_time,'unknown');
  331. Message1(unit_u_ppu_flags,tostr(headerflags));
  332. Message1(unit_u_ppu_crc,hexstr(ppufile.header.checksum,8));
  333. Message1(unit_u_ppu_crc,hexstr(ppufile.header.interface_checksum,8)+' (intfc)');
  334. Message1(unit_u_ppu_crc,hexstr(ppufile.header.indirect_checksum,8)+' (indc)');
  335. Comment(V_used,'Number of definitions: '+tostr(ppufile.header.deflistsize));
  336. Comment(V_used,'Number of symbols: '+tostr(ppufile.header.symlistsize));
  337. do_compile:=false;
  338. openppu:=true;
  339. end;
  340. function tppumodule.search_unit_files(onlysource:boolean):boolean;
  341. var
  342. found : boolean;
  343. begin
  344. found:=false;
  345. if search_unit(onlysource,false) then
  346. found:=true;
  347. if (not found) and
  348. (length(modulename^)>8) and
  349. search_unit(onlysource,true) then
  350. found:=true;
  351. search_unit_files:=found;
  352. end;
  353. function tppumodule.search_unit(onlysource,shortname:boolean):boolean;
  354. var
  355. singlepathstring,
  356. filename : TCmdStr;
  357. Function UnitExists(const ext:string;var foundfile:TCmdStr;const prefix:TCmdStr):boolean;
  358. var
  359. s : tcmdstr;
  360. begin
  361. if CheckVerbosity(V_Tried) then
  362. Message1(unit_t_unitsearch,Singlepathstring+filename+ext);
  363. s:=FileName+ext;
  364. if prefix<>'' then
  365. s:=prefix+'.'+s;
  366. UnitExists:=FindFile(s,Singlepathstring,true,foundfile);
  367. end;
  368. Function PPUSearchPath(const s,prefix:TCmdStr):boolean;
  369. var
  370. found : boolean;
  371. hs,
  372. newname : TCmdStr;
  373. begin
  374. Found:=false;
  375. singlepathstring:=FixPath(s,false);
  376. { Check for PPU file }
  377. Found:=UnitExists(target_info.unitext,hs,prefix);
  378. if Found then
  379. Begin
  380. SetFileName(hs,false);
  381. if prefix<>'' then
  382. begin
  383. newname:=prefix+'.'+realmodulename^;
  384. stringdispose(realmodulename);
  385. realmodulename:=stringdup(newname);
  386. stringdispose(modulename);
  387. modulename:=stringdup(upper(newname));
  388. end;
  389. Found:=openppufile;
  390. End;
  391. PPUSearchPath:=Found;
  392. end;
  393. Function SourceSearchPath(const s,prefix:TCmdStr):boolean;
  394. var
  395. found : boolean;
  396. hs,
  397. newname : TCmdStr;
  398. begin
  399. Found:=false;
  400. singlepathstring:=FixPath(s,false);
  401. { Check for Sources }
  402. ppufile:=nil;
  403. do_compile:=true;
  404. recompile_reason:=rr_noppu;
  405. {Check for .pp file}
  406. Found:=UnitExists(sourceext,hs,prefix);
  407. if not Found then
  408. begin
  409. { Check for .pas }
  410. Found:=UnitExists(pasext,hs,prefix);
  411. end;
  412. if not Found and
  413. ((m_mac in current_settings.modeswitches) or
  414. (tf_p_ext_support in target_info.flags)) then
  415. begin
  416. { Check for .p, if mode is macpas}
  417. Found:=UnitExists(pext,hs,prefix);
  418. end;
  419. mainsource:='';
  420. if Found then
  421. begin
  422. sources_avail:=true;
  423. { Load Filenames when found }
  424. mainsource:=hs;
  425. SetFileName(hs,false);
  426. if prefix<>'' then
  427. begin
  428. newname:=prefix+'.'+realmodulename^;
  429. stringdispose(realmodulename);
  430. realmodulename:=stringdup(newname);
  431. stringdispose(modulename);
  432. modulename:=stringdup(upper(newname));
  433. end;
  434. end
  435. else
  436. sources_avail:=false;
  437. SourceSearchPath:=Found;
  438. end;
  439. Function SearchPath(const s,prefix:TCmdStr):boolean;
  440. var
  441. found : boolean;
  442. begin
  443. { First check for a ppu, then for the source }
  444. found:=false;
  445. if not onlysource then
  446. found:=PPUSearchPath(s,prefix);
  447. if not found then
  448. found:=SourceSearchPath(s,prefix);
  449. SearchPath:=found;
  450. end;
  451. Function SearchPathList(list:TSearchPathList;const prefix:TCmdStr):boolean;
  452. var
  453. hp : TCmdStrListItem;
  454. found : boolean;
  455. begin
  456. found:=false;
  457. hp:=TCmdStrListItem(list.First);
  458. while assigned(hp) do
  459. begin
  460. found:=SearchPath(hp.Str,prefix);
  461. if found then
  462. break;
  463. hp:=TCmdStrListItem(hp.next);
  464. end;
  465. SearchPathList:=found;
  466. end;
  467. function SearchPPUPaths(const prefix:TCmdStr):boolean;
  468. begin
  469. result:=PPUSearchPath('.',prefix);
  470. if (not result) and (outputpath<>'') then
  471. result:=PPUSearchPath(outputpath,prefix);
  472. if (not result) and Assigned(main_module) and (main_module.Path<>'') then
  473. result:=PPUSearchPath(main_module.Path,prefix);
  474. end;
  475. function SearchSourcePaths(const prefix:TCmdStr):boolean;
  476. begin
  477. result:=SourceSearchPath('.',prefix);
  478. if (not result) and Assigned(main_module) and (main_module.Path<>'') then
  479. result:=SourceSearchPath(main_module.Path,prefix);
  480. if (not result) and Assigned(loaded_from) then
  481. result:=SearchPathList(loaded_from.LocalUnitSearchPath,prefix);
  482. if not result then
  483. result:=SearchPathList(UnitSearchPath,prefix);
  484. end;
  485. var
  486. fnd : boolean;
  487. hs : TPathStr;
  488. nsitem : TCmdStrListItem;
  489. begin
  490. if shortname then
  491. filename:=FixFileName(Copy(realmodulename^,1,8))
  492. else
  493. filename:=FixFileName(realmodulename^);
  494. { try to find unit
  495. 1. look for ppu in cwd
  496. 2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
  497. 3. look for ppu in maindir
  498. 4. look for the specified source file (from the uses line)
  499. 5. look for source in cwd
  500. 6. look for source in maindir
  501. 7. local unit pathlist
  502. 8. global unit pathlist
  503. 9. for each default namespace:
  504. repeat 1 - 3 and 5 - 8 with namespace as prefix }
  505. fnd:=false;
  506. if not onlysource then
  507. fnd:=SearchPPUPaths('');
  508. if (not fnd) and (sourcefn<>'') then
  509. begin
  510. { the full filename is specified so we can't use here the
  511. searchpath (PFV) }
  512. if CheckVerbosity(V_Tried) then
  513. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,sourceext));
  514. fnd:=FindFile(ChangeFileExt(sourcefn,sourceext),'',true,hs);
  515. if not fnd then
  516. begin
  517. if CheckVerbosity(V_Tried) then
  518. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,pasext));
  519. fnd:=FindFile(ChangeFileExt(sourcefn,pasext),'',true,hs);
  520. end;
  521. if not fnd and
  522. ((m_mac in current_settings.modeswitches) or
  523. (tf_p_ext_support in target_info.flags)) then
  524. begin
  525. if CheckVerbosity(V_Tried) then
  526. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,pext));
  527. fnd:=FindFile(ChangeFileExt(sourcefn,pext),'',true,hs);
  528. end;
  529. if fnd then
  530. begin
  531. sources_avail:=true;
  532. do_compile:=true;
  533. recompile_reason:=rr_noppu;
  534. mainsource:=hs;
  535. SetFileName(hs,false);
  536. end;
  537. end;
  538. if not fnd then
  539. begin
  540. fnd:=SearchSourcePaths('');
  541. if not fnd and (namespacelist.count>0) then
  542. begin
  543. nsitem:=TCmdStrListItem(namespacelist.first);
  544. while assigned(nsitem) do
  545. begin
  546. if not onlysource then
  547. begin
  548. fnd:=SearchPPUPaths(nsitem.str);
  549. if fnd then
  550. break;
  551. end;
  552. fnd:=SearchSourcePaths(nsitem.str);
  553. if fnd then
  554. break;
  555. nsitem:=TCmdStrListItem(nsitem.next);
  556. end;
  557. if assigned(nsitem) then
  558. nsprefix:=nsitem.str;
  559. end;
  560. end;
  561. search_unit:=fnd;
  562. end;
  563. function tppumodule.loadfrompackage: boolean;
  564. (*var
  565. singlepathstring,
  566. filename : TCmdStr;
  567. Function UnitExists(const ext:string;var foundfile:TCmdStr):boolean;
  568. begin
  569. if CheckVerbosity(V_Tried) then
  570. Message1(unit_t_unitsearch,Singlepathstring+filename);
  571. UnitExists:=FindFile(FileName,Singlepathstring,true,foundfile);
  572. end;
  573. Function PPUSearchPath(const s:TCmdStr):boolean;
  574. var
  575. found : boolean;
  576. hs : TCmdStr;
  577. begin
  578. Found:=false;
  579. singlepathstring:=FixPath(s,false);
  580. { Check for PPU file }
  581. Found:=UnitExists(target_info.unitext,hs);
  582. if Found then
  583. Begin
  584. SetFileName(hs,false);
  585. //Found:=OpenPPU;
  586. End;
  587. PPUSearchPath:=Found;
  588. end;
  589. Function SearchPathList(list:TSearchPathList):boolean;
  590. var
  591. hp : TCmdStrListItem;
  592. found : boolean;
  593. begin
  594. found:=false;
  595. hp:=TCmdStrListItem(list.First);
  596. while assigned(hp) do
  597. begin
  598. found:=PPUSearchPath(hp.Str);
  599. if found then
  600. break;
  601. hp:=TCmdStrListItem(hp.next);
  602. end;
  603. SearchPathList:=found;
  604. end;*)
  605. var
  606. pkg : ppackageentry;
  607. pkgunit : pcontainedunit;
  608. i,idx : longint;
  609. strm : TCStream;
  610. begin
  611. result:=false;
  612. for i:=0 to packagelist.count-1 do
  613. begin
  614. pkg:=ppackageentry(packagelist[i]);
  615. if not assigned(pkg^.package) then
  616. internalerror(2013053103);
  617. idx:=pkg^.package.containedmodules.FindIndexOf(modulename^);
  618. if idx>=0 then
  619. begin
  620. { the unit is part of this package }
  621. pkgunit:=pcontainedunit(pkg^.package.containedmodules[idx]);
  622. if not assigned(pkgunit^.module) then
  623. pkgunit^.module:=self;
  624. { ToDo: check whether we really don't need this anymore }
  625. {filename:=pkgunit^.ppufile;
  626. if not SearchPathList(unitsearchpath) then
  627. exit};
  628. strm:=tpcppackage(pkg^.package).getmodulestream(self);
  629. if not assigned(strm) then
  630. internalerror(2015103002);
  631. if not openppustream(strm) then
  632. exit;
  633. package:=pkg^.package;
  634. Message2(unit_u_loading_from_package,modulename^,pkg^.package.packagename^);
  635. { now load the unit and all used units }
  636. load_interface;
  637. setdefgeneration;
  638. load_usedunits;
  639. Message1(unit_u_finished_loading_unit,modulename^);
  640. result:=true;
  641. break;
  642. end;
  643. end;
  644. end;
  645. procedure tppumodule.buildderefunitimportsyms;
  646. var
  647. i : longint;
  648. deref : pderef;
  649. begin
  650. for i:=0 to unitimportsyms.count-1 do
  651. begin
  652. new(deref);
  653. deref^.build(unitimportsyms[i]);
  654. unitimportsymsderefs.add(deref);
  655. end;
  656. end;
  657. procedure tppumodule.derefunitimportsyms;
  658. var
  659. i : longint;
  660. sym : tsym;
  661. begin
  662. for i:=0 to unitimportsymsderefs.count-1 do
  663. begin
  664. sym:=tsym(pderef(unitimportsymsderefs[i])^.resolve);
  665. unitimportsyms.add(sym);
  666. end;
  667. end;
  668. procedure tppumodule.freederefunitimportsyms;
  669. var
  670. i : longint;
  671. deref : pderef;
  672. begin
  673. for i:=0 to unitimportsymsderefs.count-1 do
  674. begin
  675. deref:=pderef(unitimportsymsderefs[i]);
  676. system.dispose(deref);
  677. end;
  678. end;
  679. {**********************************
  680. PPU Reading/Writing Helpers
  681. ***********************************}
  682. {$IFDEF MACRO_DIFF_HINT}
  683. var
  684. is_initial: Boolean;
  685. procedure tppumodule.writeusedmacro(p:TNamedIndexItem;arg:pointer);
  686. begin
  687. if tmacro(p).is_used or is_initial then
  688. begin
  689. ppufile.putstring(p.name);
  690. ppufile.putboolean(is_initial);
  691. ppufile.putboolean(tmacro(p).is_used);
  692. end;
  693. end;
  694. procedure tppumodule.writeusedmacros;
  695. begin
  696. ppufile.do_crc:=false;
  697. is_initial:= true;
  698. initialmacrosymtable.foreach(@writeusedmacro,nil);
  699. is_initial:= false;
  700. if assigned(globalmacrosymtable) then
  701. globalmacrosymtable.foreach(@writeusedmacro,nil);
  702. localmacrosymtable.foreach(@writeusedmacro,nil);
  703. ppufile.writeentry(ibusedmacros);
  704. ppufile.do_crc:=true;
  705. end;
  706. {$ENDIF}
  707. procedure tppumodule.writesourcefiles;
  708. var
  709. hp : tinputfile;
  710. i,j : longint;
  711. begin
  712. { second write the used source files }
  713. ppufile.do_crc:=false;
  714. hp:=sourcefiles.files;
  715. { write source files directly in good order }
  716. j:=0;
  717. while assigned(hp) do
  718. begin
  719. inc(j);
  720. hp:=hp.ref_next;
  721. end;
  722. while j>0 do
  723. begin
  724. hp:=sourcefiles.files;
  725. for i:=1 to j-1 do
  726. hp:=hp.ref_next;
  727. ppufile.putstring(hp.inc_path+hp.name);
  728. ppufile.putlongint(hp.getfiletime);
  729. dec(j);
  730. end;
  731. ppufile.writeentry(ibsourcefiles);
  732. ppufile.do_crc:=true;
  733. end;
  734. procedure tppumodule.writeusedunit(intf:boolean);
  735. var
  736. hp : tused_unit;
  737. oldcrc : boolean;
  738. begin
  739. { write a reference for each used unit }
  740. hp:=tused_unit(used_units.first);
  741. while assigned(hp) do
  742. begin
  743. if hp.in_interface=intf then
  744. begin
  745. ppufile.putstring(hp.u.realmodulename^);
  746. { the checksum should not affect the crc of this unit ! (PFV) }
  747. oldcrc:=ppufile.do_crc;
  748. ppufile.do_crc:=false;
  749. ppufile.putlongint(longint(hp.checksum));
  750. ppufile.putlongint(longint(hp.interface_checksum));
  751. ppufile.putlongint(longint(hp.indirect_checksum));
  752. ppufile.do_crc:=oldcrc;
  753. { combine all indirect checksums from units used by this unit }
  754. if intf then
  755. ppufile.indirect_crc:=ppufile.indirect_crc xor hp.indirect_checksum;
  756. end;
  757. hp:=tused_unit(hp.next);
  758. end;
  759. ppufile.do_interface_crc:=true;
  760. ppufile.writeentry(ibloadunit);
  761. end;
  762. procedure tppumodule.writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  763. var
  764. hcontainer : tlinkcontainer;
  765. s : TPathStr;
  766. mask : cardinal;
  767. begin
  768. hcontainer:=TLinkContainer.Create;
  769. while not p.empty do
  770. begin
  771. s:=p.get(mask);
  772. if strippath then
  773. ppufile.putstring(ExtractFileName(s))
  774. else
  775. ppufile.putstring(s);
  776. ppufile.putlongint(mask);
  777. hcontainer.add(s,mask);
  778. end;
  779. ppufile.writeentry(id);
  780. p.Free;
  781. p:=hcontainer;
  782. end;
  783. procedure tppumodule.writederefmap;
  784. var
  785. i : longint;
  786. oldcrc : boolean;
  787. begin
  788. { This does not influence crc }
  789. oldcrc:=ppufile.do_crc;
  790. ppufile.do_crc:=false;
  791. { The unit map used for resolving }
  792. ppufile.putlongint(derefmapcnt);
  793. for i:=0 to derefmapcnt-1 do
  794. begin
  795. if not assigned(derefmap[i].u) then
  796. internalerror(2005011512);
  797. ppufile.putstring(derefmap[i].u.modulename^)
  798. end;
  799. ppufile.writeentry(ibderefmap);
  800. ppufile.do_crc:=oldcrc;
  801. end;
  802. procedure tppumodule.writederefdata;
  803. var
  804. oldcrc : boolean;
  805. len,hlen : longint;
  806. buf : array[0..1023] of byte;
  807. begin
  808. if longword(derefdataintflen)>derefdata.size then
  809. internalerror(200310223);
  810. derefdata.seek(0);
  811. { Write interface data }
  812. len:=derefdataintflen;
  813. while (len>0) do
  814. begin
  815. if len>1024 then
  816. hlen:=1024
  817. else
  818. hlen:=len;
  819. derefdata.read(buf,hlen);
  820. ppufile.putdata(buf,hlen);
  821. dec(len,hlen);
  822. end;
  823. { Write implementation data, this does not influence crc }
  824. oldcrc:=ppufile.do_crc;
  825. ppufile.do_crc:=false;
  826. len:=derefdata.size-derefdataintflen;
  827. while (len>0) do
  828. begin
  829. if len>1024 then
  830. hlen:=1024
  831. else
  832. hlen:=len;
  833. derefdata.read(buf,hlen);
  834. ppufile.putdata(buf,hlen);
  835. dec(len,hlen);
  836. end;
  837. if derefdata.pos<>derefdata.size then
  838. internalerror(200310224);
  839. ppufile.do_crc:=oldcrc;
  840. ppufile.writeentry(ibderefdata);
  841. end;
  842. procedure tppumodule.writeImportSymbols;
  843. var
  844. i,j : longint;
  845. ImportLibrary : TImportLibrary;
  846. ImportSymbol : TImportSymbol;
  847. begin
  848. for i:=0 to ImportLibraryList.Count-1 do
  849. begin
  850. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  851. ppufile.putstring(ImportLibrary.Name);
  852. ppufile.putlongint(ImportLibrary.ImportSymbolList.Count);
  853. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  854. begin
  855. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  856. ppufile.putstring(ImportSymbol.Name);
  857. ppufile.putstring(ImportSymbol.MangledName);
  858. ppufile.putlongint(ImportSymbol.OrdNr);
  859. ppufile.putbyte(byte(ImportSymbol.IsVar));
  860. end;
  861. end;
  862. ppufile.writeentry(ibImportSymbols);
  863. end;
  864. procedure tppumodule.writeResources;
  865. var
  866. res : TCmdStrListItem;
  867. begin
  868. res:=TCmdStrListItem(ResourceFiles.First);
  869. while res<>nil do
  870. begin
  871. ppufile.putstring(res.FPStr);
  872. res:=TCmdStrListItem(res.Next);
  873. end;
  874. ppufile.writeentry(ibresources);
  875. end;
  876. procedure tppumodule.writeOrderedSymbols;
  877. var
  878. res : TCmdStrListItem;
  879. begin
  880. res:=TCmdStrListItem(linkorderedsymbols.First);
  881. while res<>nil do
  882. begin
  883. ppufile.putstring(res.FPStr);
  884. res:=TCmdStrListItem(res.Next);
  885. end;
  886. ppufile.writeentry(iborderedsymbols);
  887. end;
  888. procedure tppumodule.writeunitimportsyms;
  889. var
  890. i : longint;
  891. begin
  892. ppufile.putlongint(unitimportsymsderefs.count);
  893. for i:=0 to unitimportsymsderefs.count-1 do
  894. ppufile.putderef(pderef(unitimportsymsderefs[i])^);
  895. ppufile.writeentry(ibunitimportsyms);
  896. end;
  897. procedure tppumodule.writeasmsyms(kind:tunitasmlisttype;list:tfphashobjectlist);
  898. var
  899. i : longint;
  900. sym : TAsmSymbol;
  901. begin
  902. ppufile.putbyte(ord(kind));
  903. ppufile.putlongint(list.count);
  904. for i:=0 to list.count-1 do
  905. begin
  906. sym:=TAsmSymbol(list[i]);
  907. ppufile.putstring(sym.Name);
  908. ppufile.putbyte(ord(sym.bind));
  909. ppufile.putbyte(ord(sym.typ));
  910. end;
  911. ppufile.writeentry(ibasmsymbols);
  912. end;
  913. procedure tppumodule.writeextraheader;
  914. var
  915. old_docrc: boolean;
  916. begin
  917. { create unit flags }
  918. if do_release then
  919. include(moduleflags,mf_release);
  920. if assigned(localsymtable) then
  921. include(moduleflags,mf_local_symtable);
  922. if cs_checkpointer_called in current_settings.moduleswitches then
  923. include(moduleflags,mf_checkpointer_called);
  924. {$ifdef i8086}
  925. if current_settings.x86memorymodel in [mm_medium,mm_large,mm_huge] then
  926. include(moduleflags,mf_i8086_far_code);
  927. if current_settings.x86memorymodel in [mm_compact,mm_large] then
  928. include(moduleflags,mf_i8086_far_data);
  929. if current_settings.x86memorymodel=mm_huge then
  930. include(moduleflags,mf_i8086_huge_data);
  931. if current_settings.x86memorymodel=mm_tiny then
  932. include(moduleflags,mf_i8086_cs_equals_ds);
  933. if current_settings.x86memorymodel in [mm_tiny,mm_small,mm_medium] then
  934. include(moduleflags,mf_i8086_ss_equals_ds);
  935. {$endif i8086}
  936. {$ifdef llvm}
  937. include(moduleflags,mf_llvm);
  938. {$endif}
  939. {$ifdef symansistr}
  940. include(moduleflags,mf_symansistr);
  941. {$endif}
  942. old_docrc:=ppufile.do_crc;
  943. ppufile.do_crc:=false;
  944. ppufile.putlongint(longint(CurrentPPULongVersion));
  945. ppufile.putsmallset(moduleflags);
  946. ppufile.writeentry(ibextraheader);
  947. ppufile.do_crc:=old_docrc;
  948. end;
  949. {$IFDEF MACRO_DIFF_HINT}
  950. {
  951. Define MACRO_DIFF_HINT for the whole compiler (and ppudump)
  952. to turn this facility on. Also the hint messages defined
  953. below must be commented in in the msg/errore.msg file.
  954. There is some problems with this, thats why it is shut off:
  955. At the first compilation, consider a macro which is not initially
  956. defined, but it is used (e g the check that it is undefined is true).
  957. Since it do not exist, there is no macro object where the is_used
  958. flag can be set. Later on when the macro is defined, and the ppu
  959. is opened, the check cannot detect this.
  960. Also, in which macro object should this flag be set ? It cant be set
  961. for macros in the initialmacrosymboltable since this table is shared
  962. between different files.
  963. }
  964. procedure tppumodule.readusedmacros;
  965. var
  966. hs : string;
  967. mac : tmacro;
  968. was_initial,
  969. was_used : boolean;
  970. {Reads macros which was defined or used when the module was compiled.
  971. This is done when a ppu file is open, before it possibly is parsed.}
  972. begin
  973. while not ppufile.endofentry do
  974. begin
  975. hs:=ppufile.getstring;
  976. was_initial:=ppufile.getboolean;
  977. was_used:=ppufile.getboolean;
  978. mac:=tmacro(initialmacrosymtable.Find(hs));
  979. if assigned(mac) then
  980. begin
  981. {$ifndef EXTDEBUG}
  982. { if we don't have the sources why tell }
  983. if sources_avail then
  984. {$endif ndef EXTDEBUG}
  985. if (not was_initial) and was_used then
  986. Message2(unit_h_cond_not_set_in_last_compile,hs,mainsource^);
  987. end
  988. else { not assigned }
  989. if was_initial and
  990. was_used then
  991. Message2(unit_h_cond_set_in_last_compile,hs,mainsource^);
  992. end;
  993. end;
  994. {$ENDIF}
  995. procedure tppumodule.readsourcefiles;
  996. var
  997. temp,hs : string;
  998. inc_path : string;
  999. temp_dir : TCmdStr;
  1000. main_dir : TCmdStr;
  1001. found,
  1002. is_main : boolean;
  1003. orgfiletime,
  1004. source_time : longint;
  1005. hp : tinputfile;
  1006. begin
  1007. sources_avail:=not(mf_release in moduleflags);
  1008. is_main:=true;
  1009. main_dir:='';
  1010. while not ppufile.endofentry do
  1011. begin
  1012. hs:=SetDirSeparators(ppufile.getstring);
  1013. inc_path:=ExtractFilePath(hs);
  1014. orgfiletime:=ppufile.getlongint;
  1015. temp_dir:='';
  1016. if sources_avail then
  1017. begin
  1018. if (headerflags and uf_in_library)<>0 then
  1019. begin
  1020. sources_avail:=false;
  1021. temp:=' library';
  1022. end
  1023. else if pos('Macro ',hs)=1 then
  1024. begin
  1025. { we don't want to find this file }
  1026. { but there is a problem with file indexing !! }
  1027. temp:='';
  1028. end
  1029. else
  1030. begin
  1031. { check the date of the source files:
  1032. 1 path of ppu
  1033. 2 path of main source
  1034. 3 current dir
  1035. 4 include/unit path }
  1036. Source_Time:=GetNamedFileTime(path+hs);
  1037. found:=false;
  1038. if Source_Time<>-1 then
  1039. hs:=path+hs
  1040. else
  1041. if not(is_main) then
  1042. begin
  1043. Source_Time:=GetNamedFileTime(main_dir+hs);
  1044. if Source_Time<>-1 then
  1045. hs:=main_dir+hs;
  1046. end;
  1047. if Source_Time=-1 then
  1048. Source_Time:=GetNamedFileTime(hs);
  1049. if (Source_Time=-1) then
  1050. begin
  1051. if is_main then
  1052. found:=unitsearchpath.FindFile(hs,true,temp_dir)
  1053. else
  1054. found:=includesearchpath.FindFile(hs,true,temp_dir);
  1055. if found then
  1056. begin
  1057. Source_Time:=GetNamedFileTime(temp_dir);
  1058. if Source_Time<>-1 then
  1059. hs:=temp_dir;
  1060. end;
  1061. end;
  1062. if Source_Time<>-1 then
  1063. begin
  1064. if is_main then
  1065. main_dir:=ExtractFilePath(hs);
  1066. temp:=' time '+filetimestring(source_time);
  1067. if (orgfiletime<>-1) and
  1068. (source_time<>orgfiletime) then
  1069. begin
  1070. do_compile:=true;
  1071. recompile_reason:=rr_sourcenewer;
  1072. Message2(unit_u_source_modified,hs,ppufilename,@queuecomment);
  1073. temp:=temp+' *';
  1074. end;
  1075. end
  1076. else
  1077. begin
  1078. sources_avail:=false;
  1079. temp:=' not found';
  1080. end;
  1081. hp:=tdosinputfile.create(hs);
  1082. hp.inc_path:=inc_path;
  1083. { the indexing is wrong here PM }
  1084. sourcefiles.register_file(hp);
  1085. end;
  1086. end
  1087. else
  1088. begin
  1089. { still register the source module for proper error messages
  1090. since source_avail for the module is still false, this should not hurt }
  1091. sourcefiles.register_file(tdosinputfile.create(hs));
  1092. temp:=' not available';
  1093. end;
  1094. if is_main then
  1095. begin
  1096. mainsource:=hs;
  1097. end;
  1098. Message1(unit_u_ppu_source,hs+temp,@queuecomment);
  1099. is_main:=false;
  1100. end;
  1101. { check if we want to rebuild every unit, only if the sources are
  1102. available }
  1103. if do_build and sources_avail then
  1104. begin
  1105. do_compile:=true;
  1106. recompile_reason:=rr_build;
  1107. end;
  1108. end;
  1109. procedure tppumodule.readloadunit;
  1110. var
  1111. hs : string;
  1112. pu : tused_unit;
  1113. hp : tppumodule;
  1114. indchecksum,
  1115. intfchecksum,
  1116. checksum : cardinal;
  1117. begin
  1118. while not ppufile.endofentry do
  1119. begin
  1120. hs:=ppufile.getstring;
  1121. checksum:=cardinal(ppufile.getlongint);
  1122. intfchecksum:=cardinal(ppufile.getlongint);
  1123. indchecksum:=cardinal(ppufile.getlongint);
  1124. { set the state of this unit before registering, this is
  1125. needed for a correct circular dependency check }
  1126. hp:=registerunit(self,hs,'');
  1127. pu:=addusedunit(hp,false,nil);
  1128. pu.checksum:=checksum;
  1129. pu.interface_checksum:=intfchecksum;
  1130. pu.indirect_checksum:=indchecksum;
  1131. end;
  1132. in_interface:=false;
  1133. end;
  1134. procedure tppumodule.readlinkcontainer(var p:tlinkcontainer);
  1135. var
  1136. s : string;
  1137. m : longint;
  1138. begin
  1139. while not ppufile.endofentry do
  1140. begin
  1141. s:=ppufile.getstring;
  1142. m:=ppufile.getlongint;
  1143. p.add(s,m);
  1144. end;
  1145. end;
  1146. procedure tppumodule.readderefmap;
  1147. var
  1148. i : longint;
  1149. begin
  1150. { Load unit map used for resolving }
  1151. derefmapsize:=ppufile.getlongint;
  1152. derefmapcnt:=derefmapsize;
  1153. getmem(derefmap,derefmapsize*sizeof(tderefmaprec));
  1154. fillchar(derefmap^,derefmapsize*sizeof(tderefmaprec),0);
  1155. for i:=0 to derefmapsize-1 do
  1156. derefmap[i].modulename:=ppufile.getpshortstring;
  1157. end;
  1158. procedure tppumodule.readderefdata;
  1159. var
  1160. len,hlen : longint;
  1161. buf : array[0..1023] of byte;
  1162. begin
  1163. len:=ppufile.entrysize;
  1164. while (len>0) do
  1165. begin
  1166. if len>1024 then
  1167. hlen:=1024
  1168. else
  1169. hlen:=len;
  1170. ppufile.getdata(buf,hlen);
  1171. derefdata.write(buf,hlen);
  1172. dec(len,hlen);
  1173. end;
  1174. end;
  1175. procedure tppumodule.readImportSymbols;
  1176. var
  1177. j,
  1178. extsymcnt : longint;
  1179. ImportLibrary : TImportLibrary;
  1180. extsymname : string;
  1181. extsymmangledname : string;
  1182. extsymordnr : longint;
  1183. extsymisvar : boolean;
  1184. begin
  1185. while not ppufile.endofentry do
  1186. begin
  1187. ImportLibrary:=TImportLibrary.Create(ImportLibraryList,ppufile.getstring);
  1188. extsymcnt:=ppufile.getlongint;
  1189. for j:=0 to extsymcnt-1 do
  1190. begin
  1191. extsymname:=ppufile.getstring;
  1192. extsymmangledname:=ppufile.getstring;
  1193. extsymordnr:=ppufile.getlongint;
  1194. extsymisvar:=(ppufile.getbyte<>0);
  1195. TImportSymbol.Create(ImportLibrary.ImportSymbolList,extsymname,
  1196. extsymmangledname,extsymordnr,extsymisvar);
  1197. end;
  1198. end;
  1199. end;
  1200. procedure tppumodule.readResources;
  1201. begin
  1202. while not ppufile.endofentry do
  1203. resourcefiles.Insert(ppufile.getstring);
  1204. end;
  1205. procedure tppumodule.readOrderedSymbols;
  1206. begin
  1207. while not ppufile.endofentry do
  1208. linkorderedsymbols.Concat(ppufile.getstring);
  1209. end;
  1210. procedure tppumodule.readwpofile;
  1211. var
  1212. orgwpofilename: string;
  1213. orgwpofiletime: longint;
  1214. begin
  1215. { check whether we are using the same wpo feedback input file as when
  1216. this unit was compiled (same file name and file date)
  1217. }
  1218. orgwpofilename:=ppufile.getstring;
  1219. orgwpofiletime:=ppufile.getlongint;
  1220. if (extractfilename(orgwpofilename)<>extractfilename(wpofeedbackinput)) or
  1221. (orgwpofiletime<>GetNamedFileTime(orgwpofilename)) then
  1222. { make sure we don't throw away a precompiled unit if the user simply
  1223. forgot to specify the right wpo feedback file
  1224. }
  1225. message3(unit_e_different_wpo_file,ppufilename,orgwpofilename,filetimestring(orgwpofiletime));
  1226. end;
  1227. procedure tppumodule.readunitimportsyms;
  1228. var
  1229. c,i : longint;
  1230. deref : pderef;
  1231. begin
  1232. c:=ppufile.getlongint;
  1233. for i:=0 to c-1 do
  1234. begin
  1235. new(deref);
  1236. ppufile.getderef(deref^);
  1237. unitimportsymsderefs.add(deref);
  1238. end;
  1239. end;
  1240. procedure tppumodule.readasmsyms;
  1241. var
  1242. c,i : longint;
  1243. name : TSymStr;
  1244. bind : TAsmsymbind;
  1245. typ : TAsmsymtype;
  1246. list : tfphashobjectlist;
  1247. begin
  1248. case tunitasmlisttype(ppufile.getbyte) of
  1249. ualt_public:
  1250. list:=publicasmsyms;
  1251. ualt_extern:
  1252. list:=externasmsyms;
  1253. end;
  1254. c:=ppufile.getlongint;
  1255. for i:=0 to c-1 do
  1256. begin
  1257. name:=ppufile.getstring;
  1258. bind:=TAsmsymbind(ppufile.getbyte);
  1259. typ:=TAsmsymtype(ppufile.getbyte);
  1260. TAsmSymbol.Create(list,name,bind,typ);
  1261. end;
  1262. end;
  1263. procedure tppumodule.readextraheader;
  1264. begin
  1265. longversion:=cardinal(ppufile.getlongint);
  1266. ppufile.getsmallset(moduleflags);
  1267. end;
  1268. procedure tppumodule.load_interface;
  1269. var
  1270. b : byte;
  1271. newmodulename : string;
  1272. begin
  1273. { read interface part }
  1274. repeat
  1275. b:=ppufile.readentry;
  1276. case b of
  1277. ibjvmnamespace :
  1278. begin
  1279. namespace:=ppufile.getpshortstring;
  1280. end;
  1281. ibmodulename :
  1282. begin
  1283. newmodulename:=ppufile.getstring;
  1284. if (cs_check_unit_name in current_settings.globalswitches) and
  1285. (upper(newmodulename)<>modulename^) then
  1286. Message2(unit_f_unit_name_error,realmodulename^,newmodulename);
  1287. stringdispose(modulename);
  1288. stringdispose(realmodulename);
  1289. modulename:=stringdup(upper(newmodulename));
  1290. realmodulename:=stringdup(newmodulename);
  1291. end;
  1292. ibextraheader:
  1293. begin
  1294. readextraheader;
  1295. end;
  1296. ibfeatures :
  1297. begin
  1298. ppufile.getsmallset(features);
  1299. end;
  1300. ibmoduleoptions:
  1301. begin
  1302. ppufile.getsmallset(moduleoptions);
  1303. if mo_has_deprecated_msg in moduleoptions then
  1304. begin
  1305. stringdispose(deprecatedmsg);
  1306. deprecatedmsg:=ppufile.getpshortstring;
  1307. end;
  1308. end;
  1309. ibsourcefiles :
  1310. readsourcefiles;
  1311. {$IFDEF MACRO_DIFF_HINT}
  1312. ibusedmacros :
  1313. readusedmacros;
  1314. {$ENDIF}
  1315. ibloadunit :
  1316. readloadunit;
  1317. iblinkunitofiles :
  1318. readlinkcontainer(LinkUnitOFiles);
  1319. iblinkunitstaticlibs :
  1320. readlinkcontainer(LinkUnitStaticLibs);
  1321. iblinkunitsharedlibs :
  1322. readlinkcontainer(LinkUnitSharedLibs);
  1323. iblinkotherofiles :
  1324. readlinkcontainer(LinkotherOFiles);
  1325. iblinkotherstaticlibs :
  1326. readlinkcontainer(LinkotherStaticLibs);
  1327. iblinkothersharedlibs :
  1328. readlinkcontainer(LinkotherSharedLibs);
  1329. iblinkotherframeworks :
  1330. readlinkcontainer(LinkOtherFrameworks);
  1331. ibmainname:
  1332. begin
  1333. mainname:=ppufile.getpshortstring;
  1334. if (mainaliasname<>defaultmainaliasname) then
  1335. Message1(scan_w_multiple_main_name_overrides,mainaliasname);
  1336. mainaliasname:=mainname^;
  1337. end;
  1338. ibImportSymbols :
  1339. readImportSymbols;
  1340. ibderefmap :
  1341. readderefmap;
  1342. ibderefdata :
  1343. readderefdata;
  1344. ibresources:
  1345. readResources;
  1346. iborderedsymbols:
  1347. readOrderedSymbols;
  1348. ibwpofile:
  1349. readwpofile;
  1350. ibendinterface :
  1351. break;
  1352. else
  1353. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1354. end;
  1355. { we can already stop when we know that we must recompile }
  1356. if do_compile then
  1357. exit;
  1358. until false;
  1359. end;
  1360. procedure tppumodule.load_implementation;
  1361. var
  1362. b : byte;
  1363. begin
  1364. { read implementation part }
  1365. repeat
  1366. b:=ppufile.readentry;
  1367. case b of
  1368. ibloadunit :
  1369. readloadunit;
  1370. ibasmsymbols :
  1371. readasmsyms;
  1372. ibunitimportsyms:
  1373. readunitimportsyms;
  1374. ibendimplementation :
  1375. break;
  1376. else
  1377. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1378. end;
  1379. until false;
  1380. end;
  1381. procedure tppumodule.writeppu;
  1382. begin
  1383. Message1(unit_u_ppu_write,realmodulename^);
  1384. { create unit flags }
  1385. {$ifdef cpufpemu}
  1386. if (cs_fp_emulation in current_settings.moduleswitches) then
  1387. headerflags:=headerflags or uf_fpu_emulation;
  1388. {$endif cpufpemu}
  1389. {$ifdef Test_Double_checksum_write}
  1390. Assign(CRCFile,ppufilename+'.IMP');
  1391. Rewrite(CRCFile);
  1392. {$endif def Test_Double_checksum_write}
  1393. { create new ppufile }
  1394. ppufile:=tcompilerppufile.create(ppufilename);
  1395. if not ppufile.createfile then
  1396. Message(unit_f_ppu_cannot_write);
  1397. { extra header (sub version, module flags) }
  1398. writeextraheader;
  1399. { first the (JVM) namespace }
  1400. if assigned(namespace) then
  1401. begin
  1402. ppufile.putstring(namespace^);
  1403. ppufile.writeentry(ibjvmnamespace);
  1404. end;
  1405. { the unitname }
  1406. ppufile.putstring(realmodulename^);
  1407. ppufile.writeentry(ibmodulename);
  1408. ppufile.putsmallset(moduleoptions);
  1409. if mo_has_deprecated_msg in moduleoptions then
  1410. ppufile.putstring(deprecatedmsg^);
  1411. ppufile.writeentry(ibmoduleoptions);
  1412. { write the alternate main procedure name if any }
  1413. if assigned(mainname) then
  1414. begin
  1415. ppufile.putstring(mainname^);
  1416. ppufile.writeentry(ibmainname);
  1417. end;
  1418. if cs_compilesystem in current_settings.moduleswitches then
  1419. begin
  1420. ppufile.putsmallset(features);
  1421. ppufile.writeentry(ibfeatures);
  1422. end;
  1423. writesourcefiles;
  1424. {$IFDEF MACRO_DIFF_HINT}
  1425. writeusedmacros;
  1426. {$ENDIF}
  1427. { write interface uses }
  1428. writeusedunit(true);
  1429. { write the objectfiles and libraries that come for this unit,
  1430. preserve the containers because they are still needed to load
  1431. the link.res.
  1432. All doesn't depend on the crc! It doesn't matter
  1433. if a unit is in a .o or .a file }
  1434. ppufile.do_crc:=false;
  1435. { write after source files, so that we know whether or not the compiler
  1436. will recompile the unit when checking whether the correct wpo file is
  1437. used (if it will recompile the unit anyway, it doesn't matter)
  1438. }
  1439. if (wpofeedbackinput<>'') then
  1440. begin
  1441. ppufile.putstring(wpofeedbackinput);
  1442. ppufile.putlongint(getnamedfiletime(wpofeedbackinput));
  1443. ppufile.writeentry(ibwpofile);
  1444. end;
  1445. writelinkcontainer(linkunitofiles,iblinkunitofiles,true);
  1446. writelinkcontainer(linkunitstaticlibs,iblinkunitstaticlibs,true);
  1447. writelinkcontainer(linkunitsharedlibs,iblinkunitsharedlibs,true);
  1448. writelinkcontainer(linkotherofiles,iblinkotherofiles,false);
  1449. writelinkcontainer(linkotherstaticlibs,iblinkotherstaticlibs,true);
  1450. writelinkcontainer(linkothersharedlibs,iblinkothersharedlibs,true);
  1451. writelinkcontainer(linkotherframeworks,iblinkotherframeworks,true);
  1452. writeImportSymbols;
  1453. writeResources;
  1454. writeOrderedSymbols;
  1455. ppufile.do_crc:=true;
  1456. { generate implementation deref data, the interface deref data is
  1457. already generated when calculating the interface crc }
  1458. if (cs_compilesystem in current_settings.moduleswitches) then
  1459. begin
  1460. tstoredsymtable(globalsymtable).buildderef;
  1461. derefdataintflen:=derefdata.size;
  1462. end
  1463. else
  1464. { the unit may have been re-resolved, in which case the current
  1465. position in derefdata is not necessarily at the end }
  1466. derefdata.seek(derefdata.size);
  1467. tstoredsymtable(globalsymtable).buildderefimpl;
  1468. tunitwpoinfo(wpoinfo).buildderef;
  1469. tunitwpoinfo(wpoinfo).buildderefimpl;
  1470. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1471. begin
  1472. tstoredsymtable(globalmacrosymtable).buildderef;
  1473. tstoredsymtable(globalmacrosymtable).buildderefimpl;
  1474. end;
  1475. if mf_local_symtable in moduleflags then
  1476. tstoredsymtable(localsymtable).buildderef_registered;
  1477. buildderefunitimportsyms;
  1478. writederefmap;
  1479. writederefdata;
  1480. ppufile.writeentry(ibendinterface);
  1481. { write the symtable entries }
  1482. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1483. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1484. begin
  1485. ppufile.putbyte(byte(true));
  1486. ppufile.writeentry(ibexportedmacros);
  1487. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1488. end
  1489. else
  1490. begin
  1491. ppufile.putbyte(byte(false));
  1492. ppufile.writeentry(ibexportedmacros);
  1493. end;
  1494. { everything after this doesn't affect the crc }
  1495. ppufile.do_crc:=false;
  1496. { write implementation uses }
  1497. writeusedunit(false);
  1498. { write all public assembler symbols }
  1499. writeasmsyms(ualt_public,publicasmsyms);
  1500. { write all external assembler symbols }
  1501. writeasmsyms(ualt_extern,externasmsyms);
  1502. { write all symbols imported from another unit }
  1503. writeunitimportsyms;
  1504. { end of implementation }
  1505. ppufile.writeentry(ibendimplementation);
  1506. { write static symtable
  1507. needed for local debugging of unit functions }
  1508. if mf_local_symtable in moduleflags then
  1509. tstoredsymtable(localsymtable).ppuwrite(ppufile);
  1510. { write whole program optimisation-related information }
  1511. tunitwpoinfo(wpoinfo).ppuwrite(ppufile);
  1512. { the last entry ibend is written automatically }
  1513. { flush to be sure }
  1514. ppufile.flush;
  1515. { create and write header }
  1516. ppufile.header.common.size:=ppufile.size;
  1517. ppufile.header.checksum:=ppufile.crc;
  1518. ppufile.header.interface_checksum:=ppufile.interface_crc;
  1519. ppufile.header.indirect_checksum:=ppufile.indirect_crc;
  1520. ppufile.header.common.compiler:=wordversion;
  1521. ppufile.header.common.cpu:=word(target_cpu);
  1522. ppufile.header.common.target:=word(target_info.system);
  1523. ppufile.header.common.flags:=headerflags;
  1524. ppufile.header.deflistsize:=current_module.deflist.count;
  1525. ppufile.header.symlistsize:=current_module.symlist.count;
  1526. ppufile.writeheader;
  1527. { save crc in current module also }
  1528. crc:=ppufile.crc;
  1529. interface_crc:=ppufile.interface_crc;
  1530. indirect_crc:=ppufile.indirect_crc;
  1531. {$ifdef Test_Double_checksum_write}
  1532. close(CRCFile);
  1533. {$endif Test_Double_checksum_write}
  1534. ppufile.closefile;
  1535. ppufile.free;
  1536. ppufile:=nil;
  1537. end;
  1538. procedure tppumodule.getppucrc;
  1539. begin
  1540. {$ifdef Test_Double_checksum_write}
  1541. Assign(CRCFile,ppufilename+'.INT');
  1542. Rewrite(CRCFile);
  1543. {$endif def Test_Double_checksum_write}
  1544. { create new ppufile }
  1545. ppufile:=tcompilerppufile.create(ppufilename);
  1546. ppufile.crc_only:=true;
  1547. if not ppufile.createfile then
  1548. Message(unit_f_ppu_cannot_write);
  1549. { first the (JVM) namespace }
  1550. if assigned(namespace) then
  1551. begin
  1552. ppufile.putstring(namespace^);
  1553. ppufile.writeentry(ibjvmnamespace);
  1554. end;
  1555. { the unitname }
  1556. ppufile.putstring(realmodulename^);
  1557. ppufile.writeentry(ibmodulename);
  1558. { extra header (sub version, module flags) }
  1559. writeextraheader;
  1560. ppufile.putsmallset(moduleoptions);
  1561. if mo_has_deprecated_msg in moduleoptions then
  1562. ppufile.putstring(deprecatedmsg^);
  1563. ppufile.writeentry(ibmoduleoptions);
  1564. { the interface units affect the crc }
  1565. writeusedunit(true);
  1566. { deref data of interface that affect the crc }
  1567. derefdata.reset;
  1568. tstoredsymtable(globalsymtable).buildderef;
  1569. derefdataintflen:=derefdata.size;
  1570. writederefmap;
  1571. writederefdata;
  1572. ppufile.writeentry(ibendinterface);
  1573. { write the symtable entries }
  1574. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1575. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1576. begin
  1577. ppufile.putbyte(byte(true));
  1578. ppufile.writeentry(ibexportedmacros);
  1579. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1580. end
  1581. else
  1582. begin
  1583. ppufile.putbyte(byte(false));
  1584. ppufile.writeentry(ibexportedmacros);
  1585. end;
  1586. { save crc }
  1587. crc:=ppufile.crc;
  1588. interface_crc:=ppufile.interface_crc;
  1589. indirect_crc:=ppufile.indirect_crc;
  1590. { end of implementation, to generate a correct ppufile
  1591. for ppudump when using INTFPPU define }
  1592. ppufile.writeentry(ibendimplementation);
  1593. {$ifdef Test_Double_checksum}
  1594. crc_array:=ppufile.crc_test;
  1595. ppufile.crc_test:=nil;
  1596. crc_size:=ppufile.crc_index2;
  1597. crc_array2:=ppufile.crc_test2;
  1598. ppufile.crc_test2:=nil;
  1599. crc_size2:=ppufile.crc_index2;
  1600. {$endif Test_Double_checksum}
  1601. {$ifdef Test_Double_checksum_write}
  1602. close(CRCFile);
  1603. {$endif Test_Double_checksum_write}
  1604. { create and write header, this will only be used
  1605. for debugging purposes }
  1606. ppufile.header.common.size:=ppufile.size;
  1607. ppufile.header.checksum:=ppufile.crc;
  1608. ppufile.header.interface_checksum:=ppufile.interface_crc;
  1609. ppufile.header.indirect_checksum:=ppufile.indirect_crc;
  1610. ppufile.header.common.compiler:=wordversion;
  1611. ppufile.header.common.cpu:=word(target_cpu);
  1612. ppufile.header.common.target:=word(target_info.system);
  1613. ppufile.header.common.flags:=headerflags;
  1614. ppufile.writeheader;
  1615. ppufile.closefile;
  1616. ppufile.free;
  1617. ppufile:=nil;
  1618. end;
  1619. procedure tppumodule.load_usedunits;
  1620. var
  1621. pu : tused_unit;
  1622. begin
  1623. if current_module<>self then
  1624. internalerror(200212284);
  1625. { load the used units from interface }
  1626. in_interface:=true;
  1627. pu:=tused_unit(used_units.first);
  1628. while assigned(pu) do
  1629. begin
  1630. if pu.in_interface then
  1631. begin
  1632. tppumodule(pu.u).loadppu;
  1633. { if this unit is compiled we can stop }
  1634. if state=ms_compiled then
  1635. exit;
  1636. { add this unit to the dependencies }
  1637. pu.u.adddependency(self);
  1638. { need to recompile the current unit, check the interface
  1639. crc. And when not compiled with -Ur then check the complete
  1640. crc }
  1641. if (pu.u.interface_crc<>pu.interface_checksum) or
  1642. (pu.u.indirect_crc<>pu.indirect_checksum) or
  1643. (
  1644. (not(mf_release in moduleflags)) and
  1645. (pu.u.crc<>pu.checksum)
  1646. ) then
  1647. begin
  1648. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename,@queuecomment);
  1649. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1650. if (pu.u.interface_crc<>pu.interface_checksum) then
  1651. writeln(' intfcrc change: ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1652. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1653. writeln(' indcrc change: ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
  1654. else
  1655. writeln(' implcrc change: ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
  1656. {$endif DEBUG_UNIT_CRC_CHANGES}
  1657. recompile_reason:=rr_crcchanged;
  1658. do_compile:=true;
  1659. exit;
  1660. end;
  1661. end;
  1662. pu:=tused_unit(pu.next);
  1663. end;
  1664. { ok, now load the interface of this unit }
  1665. if current_module<>self then
  1666. internalerror(200208187);
  1667. deflist.count:=ppufile.header.deflistsize;
  1668. symlist.count:=ppufile.header.symlistsize;
  1669. globalsymtable:=tglobalsymtable.create(modulename^,moduleid);
  1670. tstoredsymtable(globalsymtable).ppuload(ppufile);
  1671. if ppufile.readentry<>ibexportedmacros then
  1672. Message(unit_f_ppu_read_error);
  1673. if boolean(ppufile.getbyte) then
  1674. begin
  1675. globalmacrosymtable:=tmacrosymtable.Create(true);
  1676. tstoredsymtable(globalmacrosymtable).ppuload(ppufile)
  1677. end;
  1678. interface_compiled:=true;
  1679. { read the implementation part, containing
  1680. the implementation uses and ObjData }
  1681. in_interface:=false;
  1682. load_implementation;
  1683. { now only read the implementation uses }
  1684. pu:=tused_unit(used_units.first);
  1685. while assigned(pu) do
  1686. begin
  1687. if (not pu.in_interface) then
  1688. begin
  1689. tppumodule(pu.u).loadppu;
  1690. { if this unit is compiled we can stop }
  1691. if state=ms_compiled then
  1692. exit;
  1693. { add this unit to the dependencies }
  1694. pu.u.adddependency(self);
  1695. { need to recompile the current unit ? }
  1696. if (pu.u.interface_crc<>pu.interface_checksum) or
  1697. (pu.u.indirect_crc<>pu.indirect_checksum) then
  1698. begin
  1699. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename+' {impl}',@queuecomment);
  1700. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1701. if (pu.u.interface_crc<>pu.interface_checksum) then
  1702. writeln(' intfcrc change (2): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1703. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1704. writeln(' indcrc change (2): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8));
  1705. {$endif DEBUG_UNIT_CRC_CHANGES}
  1706. recompile_reason:=rr_crcchanged;
  1707. do_compile:=true;
  1708. exit;
  1709. end;
  1710. end;
  1711. pu:=tused_unit(pu.next);
  1712. end;
  1713. { load implementation symtable }
  1714. if mf_local_symtable in moduleflags then
  1715. begin
  1716. localsymtable:=tstaticsymtable.create(modulename^,moduleid);
  1717. tstaticsymtable(localsymtable).ppuload(ppufile);
  1718. end;
  1719. { we can now derefence all pointers to the implementation parts }
  1720. tstoredsymtable(globalsymtable).derefimpl(false);
  1721. { we've just loaded the localsymtable from the ppu file, so everything
  1722. in it was registered by definition (otherwise it wouldn't have been in
  1723. there) }
  1724. if assigned(localsymtable) then
  1725. tstoredsymtable(localsymtable).derefimpl(false);
  1726. derefunitimportsyms;
  1727. { read whole program optimisation-related information }
  1728. wpoinfo:=tunitwpoinfo.ppuload(ppufile);
  1729. tunitwpoinfo(wpoinfo).deref;
  1730. tunitwpoinfo(wpoinfo).derefimpl;
  1731. end;
  1732. function tppumodule.needrecompile:boolean;
  1733. var
  1734. pu : tused_unit;
  1735. begin
  1736. result:=false;
  1737. pu:=tused_unit(used_units.first);
  1738. while assigned(pu) do
  1739. begin
  1740. { need to recompile the current unit, check the interface
  1741. crc. And when not compiled with -Ur then check the complete
  1742. crc }
  1743. if (pu.u.interface_crc<>pu.interface_checksum) or
  1744. (pu.u.indirect_crc<>pu.indirect_checksum) or
  1745. (
  1746. (pu.in_interface) and
  1747. (pu.u.crc<>pu.checksum)
  1748. ) then
  1749. begin
  1750. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1751. if (pu.u.interface_crc<>pu.interface_checksum) then
  1752. writeln(' intfcrc change (3): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1753. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1754. writeln(' indcrc change (3): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
  1755. else
  1756. writeln(' implcrc change (3): ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
  1757. {$endif DEBUG_UNIT_CRC_CHANGES}
  1758. result:=true;
  1759. exit;
  1760. end;
  1761. pu:=tused_unit(pu.next);
  1762. end;
  1763. end;
  1764. procedure tppumodule.setdefgeneration;
  1765. begin
  1766. defsgeneration:=currentdefgeneration;
  1767. inc(currentdefgeneration);
  1768. end;
  1769. procedure tppumodule.reload_flagged_units;
  1770. var
  1771. hp : tppumodule;
  1772. begin
  1773. { now reload all dependent units with outdated defs }
  1774. hp:=tppumodule(loaded_units.first);
  1775. while assigned(hp) do
  1776. begin
  1777. if hp.do_reload and
  1778. (hp.defsgeneration<defsgeneration) then
  1779. begin
  1780. hp.defsgeneration:=defsgeneration;
  1781. hp.loadppu
  1782. end
  1783. else
  1784. hp.do_reload:=false;
  1785. hp:=tppumodule(hp.next);
  1786. end;
  1787. end;
  1788. procedure tppumodule.end_of_parsing;
  1789. begin
  1790. { module is now compiled }
  1791. state:=ms_compiled;
  1792. { free ppu }
  1793. if assigned(ppufile) then
  1794. begin
  1795. ppufile.free;
  1796. ppufile:=nil;
  1797. end;
  1798. inherited end_of_parsing;
  1799. end;
  1800. procedure tppumodule.loadppu;
  1801. const
  1802. ImplIntf : array[boolean] of string[15]=('implementation','interface');
  1803. var
  1804. do_load,
  1805. second_time : boolean;
  1806. old_current_module : tmodule;
  1807. pu : tused_unit;
  1808. begin
  1809. old_current_module:=current_module;
  1810. Message3(unit_u_load_unit,old_current_module.modulename^,
  1811. ImplIntf[old_current_module.in_interface],
  1812. modulename^);
  1813. { Update loaded_from to detect cycles }
  1814. loaded_from:=old_current_module;
  1815. { check if the globalsymtable is already available, but
  1816. we must reload when the do_reload flag is set }
  1817. if (not do_reload) and
  1818. assigned(globalsymtable) then
  1819. exit;
  1820. { reset }
  1821. do_load:=true;
  1822. second_time:=false;
  1823. set_current_module(self);
  1824. { try to load it as a package unit first }
  1825. if (packagelist.count>0) and loadfrompackage then
  1826. begin
  1827. do_load:=false;
  1828. do_reload:=false;
  1829. state:=ms_compiled;
  1830. { PPU is not needed anymore }
  1831. if assigned(ppufile) then
  1832. begin
  1833. ppufile.closefile;
  1834. ppufile.free;
  1835. ppufile:=nil;
  1836. end;
  1837. { add the unit to the used units list of the program }
  1838. usedunits.concat(tused_unit.create(self,true,false,nil));
  1839. end;
  1840. { A force reload }
  1841. if do_reload then
  1842. begin
  1843. Message(unit_u_forced_reload);
  1844. do_reload:=false;
  1845. { When the unit is already loaded or being loaded
  1846. we can maybe skip a complete reload/recompile }
  1847. if assigned(globalsymtable) and
  1848. (not needrecompile) then
  1849. begin
  1850. { When we don't have any data stored yet there
  1851. is nothing to resolve }
  1852. if interface_compiled then
  1853. begin
  1854. Message1(unit_u_reresolving_unit,modulename^);
  1855. tstoredsymtable(globalsymtable).deref(false);
  1856. tstoredsymtable(globalsymtable).derefimpl(false);
  1857. if assigned(localsymtable) then
  1858. begin
  1859. { we have only builderef(impl)'d the registered symbols of
  1860. the localsymtable -> also only deref those again }
  1861. tstoredsymtable(localsymtable).deref(true);
  1862. tstoredsymtable(localsymtable).derefimpl(true);
  1863. end;
  1864. if assigned(wpoinfo) then
  1865. begin
  1866. tunitwpoinfo(wpoinfo).deref;
  1867. tunitwpoinfo(wpoinfo).derefimpl;
  1868. end;
  1869. { We have to flag the units that depend on this unit even
  1870. though it didn't change, because they might also
  1871. indirectly depend on the unit that did change (e.g.,
  1872. in case rgobj, rgx86 and rgcpu have been compiled
  1873. already, and then rgobj is recompiled for some reason
  1874. -> rgx86 is re-reresolved, but the vmtentries of trgcpu
  1875. must also be re-resolved, because they will also contain
  1876. pointers to procdefs in the old trgobj (in case of a
  1877. recompile, all old defs are freed) }
  1878. flagdependent(old_current_module);
  1879. reload_flagged_units;
  1880. end
  1881. else
  1882. Message1(unit_u_skipping_reresolving_unit,modulename^);
  1883. do_load:=false;
  1884. end;
  1885. end;
  1886. if do_load then
  1887. begin
  1888. { loading the unit for a second time? }
  1889. if state=ms_registered then
  1890. state:=ms_load
  1891. else
  1892. begin
  1893. { try to load the unit a second time first }
  1894. Message1(unit_u_second_load_unit,modulename^);
  1895. Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
  1896. { Flag modules to reload }
  1897. flagdependent(old_current_module);
  1898. { Reset the module }
  1899. reset;
  1900. if state in [ms_compile,ms_second_compile] then
  1901. begin
  1902. Message1(unit_u_second_compile_unit,modulename^);
  1903. state:=ms_second_compile;
  1904. do_compile:=true;
  1905. end
  1906. else
  1907. state:=ms_second_load;
  1908. second_time:=true;
  1909. end;
  1910. { close old_current_ppu on system that are
  1911. short on file handles like DOS PM }
  1912. {$ifdef SHORT_ON_FILE_HANDLES}
  1913. if old_current_module.is_unit and
  1914. assigned(tppumodule(old_current_module).ppufile) then
  1915. tppumodule(old_current_module).ppufile.tempclose;
  1916. {$endif SHORT_ON_FILE_HANDLES}
  1917. { try to opening ppu, skip this when we already
  1918. know that we need to compile the unit }
  1919. if not do_compile then
  1920. begin
  1921. Message1(unit_u_loading_unit,modulename^);
  1922. search_unit_files(false);
  1923. if not do_compile then
  1924. begin
  1925. load_interface;
  1926. setdefgeneration;
  1927. if not do_compile then
  1928. begin
  1929. load_usedunits;
  1930. if not do_compile then
  1931. Message1(unit_u_finished_loading_unit,modulename^);
  1932. end;
  1933. end;
  1934. { PPU is not needed anymore }
  1935. if assigned(ppufile) then
  1936. begin
  1937. ppufile.closefile;
  1938. ppufile.free;
  1939. ppufile:=nil;
  1940. end;
  1941. end;
  1942. { Do we need to recompile the unit }
  1943. if do_compile then
  1944. begin
  1945. { recompile the unit or give a fatal error if sources not available }
  1946. if not(sources_avail) then
  1947. begin
  1948. search_unit_files(true);
  1949. if not(sources_avail) then
  1950. begin
  1951. printcomments;
  1952. if recompile_reason=rr_noppu then
  1953. begin
  1954. pu:=tused_unit(loaded_from.used_units.first);
  1955. while assigned(pu) do
  1956. begin
  1957. if pu.u=self then
  1958. break;
  1959. pu:=tused_unit(pu.next);
  1960. end;
  1961. if assigned(pu) and assigned(pu.unitsym) then
  1962. MessagePos2(pu.unitsym.fileinfo,unit_f_cant_find_ppu,realmodulename^,loaded_from.realmodulename^)
  1963. else
  1964. Message2(unit_f_cant_find_ppu,realmodulename^,loaded_from.realmodulename^);
  1965. end
  1966. else
  1967. Message1(unit_f_cant_compile_unit,realmodulename^);
  1968. end;
  1969. end;
  1970. { we found the sources, we do not need the verbose messages anymore }
  1971. if comments <> nil then
  1972. begin
  1973. comments.free;
  1974. comments:=nil;
  1975. end;
  1976. { Flag modules to reload }
  1977. flagdependent(old_current_module);
  1978. { Reset the module }
  1979. reset;
  1980. { compile this module }
  1981. if not(state in [ms_compile,ms_second_compile]) then
  1982. state:=ms_compile;
  1983. compile(mainsource);
  1984. setdefgeneration;
  1985. end
  1986. else
  1987. state:=ms_compiled;
  1988. if current_module<>self then
  1989. internalerror(200212282);
  1990. if in_interface then
  1991. internalerror(200212283);
  1992. { for a second_time recompile reload all dependent units,
  1993. for a first time compile register the unit _once_ }
  1994. if second_time then
  1995. reload_flagged_units
  1996. else
  1997. usedunits.concat(tused_unit.create(self,true,false,nil));
  1998. { reopen the old module }
  1999. {$ifdef SHORT_ON_FILE_HANDLES}
  2000. if old_current_module.is_unit and
  2001. assigned(tppumodule(old_current_module).ppufile) then
  2002. tppumodule(old_current_module).ppufile.tempopen;
  2003. {$endif SHORT_ON_FILE_HANDLES}
  2004. end;
  2005. { we are back, restore current_module }
  2006. set_current_module(old_current_module);
  2007. end;
  2008. {*****************************************************************************
  2009. RegisterUnit
  2010. *****************************************************************************}
  2011. function registerunit(callermodule:tmodule;const s : TIDString;const fn:string) : tppumodule;
  2012. var
  2013. ups : TIDString;
  2014. hp : tppumodule;
  2015. hp2 : tmodule;
  2016. begin
  2017. { Info }
  2018. ups:=upper(s);
  2019. { search all loaded units }
  2020. hp:=tppumodule(loaded_units.first);
  2021. while assigned(hp) do
  2022. begin
  2023. if hp.modulename^=ups then
  2024. begin
  2025. { only check for units. The main program is also
  2026. as a unit in the loaded_units list. We simply need
  2027. to ignore this entry (PFV) }
  2028. if hp.is_unit then
  2029. begin
  2030. { both units in interface ? }
  2031. if callermodule.in_interface and
  2032. hp.in_interface then
  2033. begin
  2034. { check for a cycle }
  2035. hp2:=callermodule.loaded_from;
  2036. while assigned(hp2) and (hp2<>hp) do
  2037. begin
  2038. if hp2.in_interface then
  2039. hp2:=hp2.loaded_from
  2040. else
  2041. hp2:=nil;
  2042. end;
  2043. if assigned(hp2) then
  2044. Message2(unit_f_circular_unit_reference,callermodule.realmodulename^,hp.realmodulename^);
  2045. end;
  2046. break;
  2047. end;
  2048. end;
  2049. { the next unit }
  2050. hp:=tppumodule(hp.next);
  2051. end;
  2052. { the unit is not in the loaded units,
  2053. we create an entry and register the unit }
  2054. if not assigned(hp) then
  2055. begin
  2056. Message1(unit_u_registering_new_unit,Upper(s));
  2057. hp:=tppumodule.create(callermodule,s,fn,true);
  2058. hp.loaded_from:=callermodule;
  2059. addloadedunit(hp);
  2060. end;
  2061. { return }
  2062. registerunit:=hp;
  2063. end;
  2064. end.