fppu.pas 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273
  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. old_docrc:=ppufile.do_crc;
  940. ppufile.do_crc:=false;
  941. ppufile.putlongint(longint(CurrentPPULongVersion));
  942. ppufile.putsmallset(moduleflags);
  943. ppufile.writeentry(ibextraheader);
  944. ppufile.do_crc:=old_docrc;
  945. end;
  946. {$IFDEF MACRO_DIFF_HINT}
  947. {
  948. Define MACRO_DIFF_HINT for the whole compiler (and ppudump)
  949. to turn this facility on. Also the hint messages defined
  950. below must be commented in in the msg/errore.msg file.
  951. There is some problems with this, thats why it is shut off:
  952. At the first compilation, consider a macro which is not initially
  953. defined, but it is used (e g the check that it is undefined is true).
  954. Since it do not exist, there is no macro object where the is_used
  955. flag can be set. Later on when the macro is defined, and the ppu
  956. is opened, the check cannot detect this.
  957. Also, in which macro object should this flag be set ? It cant be set
  958. for macros in the initialmacrosymboltable since this table is shared
  959. between different files.
  960. }
  961. procedure tppumodule.readusedmacros;
  962. var
  963. hs : string;
  964. mac : tmacro;
  965. was_initial,
  966. was_used : boolean;
  967. {Reads macros which was defined or used when the module was compiled.
  968. This is done when a ppu file is open, before it possibly is parsed.}
  969. begin
  970. while not ppufile.endofentry do
  971. begin
  972. hs:=ppufile.getstring;
  973. was_initial:=ppufile.getboolean;
  974. was_used:=ppufile.getboolean;
  975. mac:=tmacro(initialmacrosymtable.Find(hs));
  976. if assigned(mac) then
  977. begin
  978. {$ifndef EXTDEBUG}
  979. { if we don't have the sources why tell }
  980. if sources_avail then
  981. {$endif ndef EXTDEBUG}
  982. if (not was_initial) and was_used then
  983. Message2(unit_h_cond_not_set_in_last_compile,hs,mainsource^);
  984. end
  985. else { not assigned }
  986. if was_initial and
  987. was_used then
  988. Message2(unit_h_cond_set_in_last_compile,hs,mainsource^);
  989. end;
  990. end;
  991. {$ENDIF}
  992. procedure tppumodule.readsourcefiles;
  993. var
  994. temp,hs : string;
  995. inc_path : string;
  996. temp_dir : TCmdStr;
  997. main_dir : TCmdStr;
  998. found,
  999. is_main : boolean;
  1000. orgfiletime,
  1001. source_time : longint;
  1002. hp : tinputfile;
  1003. begin
  1004. sources_avail:=not(mf_release in moduleflags);
  1005. is_main:=true;
  1006. main_dir:='';
  1007. while not ppufile.endofentry do
  1008. begin
  1009. hs:=SetDirSeparators(ppufile.getstring);
  1010. inc_path:=ExtractFilePath(hs);
  1011. orgfiletime:=ppufile.getlongint;
  1012. temp_dir:='';
  1013. if sources_avail then
  1014. begin
  1015. if (headerflags and uf_in_library)<>0 then
  1016. begin
  1017. sources_avail:=false;
  1018. temp:=' library';
  1019. end
  1020. else if pos('Macro ',hs)=1 then
  1021. begin
  1022. { we don't want to find this file }
  1023. { but there is a problem with file indexing !! }
  1024. temp:='';
  1025. end
  1026. else
  1027. begin
  1028. { check the date of the source files:
  1029. 1 path of ppu
  1030. 2 path of main source
  1031. 3 current dir
  1032. 4 include/unit path }
  1033. Source_Time:=GetNamedFileTime(path+hs);
  1034. found:=false;
  1035. if Source_Time<>-1 then
  1036. hs:=path+hs
  1037. else
  1038. if not(is_main) then
  1039. begin
  1040. Source_Time:=GetNamedFileTime(main_dir+hs);
  1041. if Source_Time<>-1 then
  1042. hs:=main_dir+hs;
  1043. end;
  1044. if Source_Time=-1 then
  1045. Source_Time:=GetNamedFileTime(hs);
  1046. if (Source_Time=-1) then
  1047. begin
  1048. if is_main then
  1049. found:=unitsearchpath.FindFile(hs,true,temp_dir)
  1050. else
  1051. found:=includesearchpath.FindFile(hs,true,temp_dir);
  1052. if found then
  1053. begin
  1054. Source_Time:=GetNamedFileTime(temp_dir);
  1055. if Source_Time<>-1 then
  1056. hs:=temp_dir;
  1057. end;
  1058. end;
  1059. if Source_Time<>-1 then
  1060. begin
  1061. if is_main then
  1062. main_dir:=ExtractFilePath(hs);
  1063. temp:=' time '+filetimestring(source_time);
  1064. if (orgfiletime<>-1) and
  1065. (source_time<>orgfiletime) then
  1066. begin
  1067. do_compile:=true;
  1068. recompile_reason:=rr_sourcenewer;
  1069. Message2(unit_u_source_modified,hs,ppufilename,@queuecomment);
  1070. temp:=temp+' *';
  1071. end;
  1072. end
  1073. else
  1074. begin
  1075. sources_avail:=false;
  1076. temp:=' not found';
  1077. end;
  1078. hp:=tdosinputfile.create(hs);
  1079. hp.inc_path:=inc_path;
  1080. { the indexing is wrong here PM }
  1081. sourcefiles.register_file(hp);
  1082. end;
  1083. end
  1084. else
  1085. begin
  1086. { still register the source module for proper error messages
  1087. since source_avail for the module is still false, this should not hurt }
  1088. sourcefiles.register_file(tdosinputfile.create(hs));
  1089. temp:=' not available';
  1090. end;
  1091. if is_main then
  1092. begin
  1093. mainsource:=hs;
  1094. end;
  1095. Message1(unit_u_ppu_source,hs+temp,@queuecomment);
  1096. is_main:=false;
  1097. end;
  1098. { check if we want to rebuild every unit, only if the sources are
  1099. available }
  1100. if do_build and sources_avail then
  1101. begin
  1102. do_compile:=true;
  1103. recompile_reason:=rr_build;
  1104. end;
  1105. end;
  1106. procedure tppumodule.readloadunit;
  1107. var
  1108. hs : string;
  1109. pu : tused_unit;
  1110. hp : tppumodule;
  1111. indchecksum,
  1112. intfchecksum,
  1113. checksum : cardinal;
  1114. begin
  1115. while not ppufile.endofentry do
  1116. begin
  1117. hs:=ppufile.getstring;
  1118. checksum:=cardinal(ppufile.getlongint);
  1119. intfchecksum:=cardinal(ppufile.getlongint);
  1120. indchecksum:=cardinal(ppufile.getlongint);
  1121. { set the state of this unit before registering, this is
  1122. needed for a correct circular dependency check }
  1123. hp:=registerunit(self,hs,'');
  1124. pu:=addusedunit(hp,false,nil);
  1125. pu.checksum:=checksum;
  1126. pu.interface_checksum:=intfchecksum;
  1127. pu.indirect_checksum:=indchecksum;
  1128. end;
  1129. in_interface:=false;
  1130. end;
  1131. procedure tppumodule.readlinkcontainer(var p:tlinkcontainer);
  1132. var
  1133. s : string;
  1134. m : longint;
  1135. begin
  1136. while not ppufile.endofentry do
  1137. begin
  1138. s:=ppufile.getstring;
  1139. m:=ppufile.getlongint;
  1140. p.add(s,m);
  1141. end;
  1142. end;
  1143. procedure tppumodule.readderefmap;
  1144. var
  1145. i : longint;
  1146. begin
  1147. { Load unit map used for resolving }
  1148. derefmapsize:=ppufile.getlongint;
  1149. derefmapcnt:=derefmapsize;
  1150. getmem(derefmap,derefmapsize*sizeof(tderefmaprec));
  1151. fillchar(derefmap^,derefmapsize*sizeof(tderefmaprec),0);
  1152. for i:=0 to derefmapsize-1 do
  1153. derefmap[i].modulename:=ppufile.getpshortstring;
  1154. end;
  1155. procedure tppumodule.readderefdata;
  1156. var
  1157. len,hlen : longint;
  1158. buf : array[0..1023] of byte;
  1159. begin
  1160. len:=ppufile.entrysize;
  1161. while (len>0) do
  1162. begin
  1163. if len>1024 then
  1164. hlen:=1024
  1165. else
  1166. hlen:=len;
  1167. ppufile.getdata(buf,hlen);
  1168. derefdata.write(buf,hlen);
  1169. dec(len,hlen);
  1170. end;
  1171. end;
  1172. procedure tppumodule.readImportSymbols;
  1173. var
  1174. j,
  1175. extsymcnt : longint;
  1176. ImportLibrary : TImportLibrary;
  1177. extsymname : string;
  1178. extsymmangledname : string;
  1179. extsymordnr : longint;
  1180. extsymisvar : boolean;
  1181. begin
  1182. while not ppufile.endofentry do
  1183. begin
  1184. ImportLibrary:=TImportLibrary.Create(ImportLibraryList,ppufile.getstring);
  1185. extsymcnt:=ppufile.getlongint;
  1186. for j:=0 to extsymcnt-1 do
  1187. begin
  1188. extsymname:=ppufile.getstring;
  1189. extsymmangledname:=ppufile.getstring;
  1190. extsymordnr:=ppufile.getlongint;
  1191. extsymisvar:=(ppufile.getbyte<>0);
  1192. TImportSymbol.Create(ImportLibrary.ImportSymbolList,extsymname,
  1193. extsymmangledname,extsymordnr,extsymisvar);
  1194. end;
  1195. end;
  1196. end;
  1197. procedure tppumodule.readResources;
  1198. begin
  1199. while not ppufile.endofentry do
  1200. resourcefiles.Insert(ppufile.getstring);
  1201. end;
  1202. procedure tppumodule.readOrderedSymbols;
  1203. begin
  1204. while not ppufile.endofentry do
  1205. linkorderedsymbols.Concat(ppufile.getstring);
  1206. end;
  1207. procedure tppumodule.readwpofile;
  1208. var
  1209. orgwpofilename: string;
  1210. orgwpofiletime: longint;
  1211. begin
  1212. { check whether we are using the same wpo feedback input file as when
  1213. this unit was compiled (same file name and file date)
  1214. }
  1215. orgwpofilename:=ppufile.getstring;
  1216. orgwpofiletime:=ppufile.getlongint;
  1217. if (extractfilename(orgwpofilename)<>extractfilename(wpofeedbackinput)) or
  1218. (orgwpofiletime<>GetNamedFileTime(orgwpofilename)) then
  1219. { make sure we don't throw away a precompiled unit if the user simply
  1220. forgot to specify the right wpo feedback file
  1221. }
  1222. message3(unit_e_different_wpo_file,ppufilename,orgwpofilename,filetimestring(orgwpofiletime));
  1223. end;
  1224. procedure tppumodule.readunitimportsyms;
  1225. var
  1226. c,i : longint;
  1227. deref : pderef;
  1228. begin
  1229. c:=ppufile.getlongint;
  1230. for i:=0 to c-1 do
  1231. begin
  1232. new(deref);
  1233. ppufile.getderef(deref^);
  1234. unitimportsymsderefs.add(deref);
  1235. end;
  1236. end;
  1237. procedure tppumodule.readasmsyms;
  1238. var
  1239. c,i : longint;
  1240. name : TSymStr;
  1241. bind : TAsmsymbind;
  1242. typ : TAsmsymtype;
  1243. list : tfphashobjectlist;
  1244. begin
  1245. case tunitasmlisttype(ppufile.getbyte) of
  1246. ualt_public:
  1247. list:=publicasmsyms;
  1248. ualt_extern:
  1249. list:=externasmsyms;
  1250. end;
  1251. c:=ppufile.getlongint;
  1252. for i:=0 to c-1 do
  1253. begin
  1254. name:=ppufile.getstring;
  1255. bind:=TAsmsymbind(ppufile.getbyte);
  1256. typ:=TAsmsymtype(ppufile.getbyte);
  1257. TAsmSymbol.Create(list,name,bind,typ);
  1258. end;
  1259. end;
  1260. procedure tppumodule.readextraheader;
  1261. begin
  1262. longversion:=cardinal(ppufile.getlongint);
  1263. ppufile.getsmallset(moduleflags);
  1264. end;
  1265. procedure tppumodule.load_interface;
  1266. var
  1267. b : byte;
  1268. newmodulename : string;
  1269. begin
  1270. { read interface part }
  1271. repeat
  1272. b:=ppufile.readentry;
  1273. case b of
  1274. ibjvmnamespace :
  1275. begin
  1276. namespace:=ppufile.getpshortstring;
  1277. end;
  1278. ibmodulename :
  1279. begin
  1280. newmodulename:=ppufile.getstring;
  1281. if (cs_check_unit_name in current_settings.globalswitches) and
  1282. (upper(newmodulename)<>modulename^) then
  1283. Message2(unit_f_unit_name_error,realmodulename^,newmodulename);
  1284. stringdispose(modulename);
  1285. stringdispose(realmodulename);
  1286. modulename:=stringdup(upper(newmodulename));
  1287. realmodulename:=stringdup(newmodulename);
  1288. end;
  1289. ibextraheader:
  1290. begin
  1291. readextraheader;
  1292. end;
  1293. ibfeatures :
  1294. begin
  1295. ppufile.getsmallset(features);
  1296. end;
  1297. ibmoduleoptions:
  1298. begin
  1299. ppufile.getsmallset(moduleoptions);
  1300. if mo_has_deprecated_msg in moduleoptions then
  1301. begin
  1302. stringdispose(deprecatedmsg);
  1303. deprecatedmsg:=ppufile.getpshortstring;
  1304. end;
  1305. end;
  1306. ibsourcefiles :
  1307. readsourcefiles;
  1308. {$IFDEF MACRO_DIFF_HINT}
  1309. ibusedmacros :
  1310. readusedmacros;
  1311. {$ENDIF}
  1312. ibloadunit :
  1313. readloadunit;
  1314. iblinkunitofiles :
  1315. readlinkcontainer(LinkUnitOFiles);
  1316. iblinkunitstaticlibs :
  1317. readlinkcontainer(LinkUnitStaticLibs);
  1318. iblinkunitsharedlibs :
  1319. readlinkcontainer(LinkUnitSharedLibs);
  1320. iblinkotherofiles :
  1321. readlinkcontainer(LinkotherOFiles);
  1322. iblinkotherstaticlibs :
  1323. readlinkcontainer(LinkotherStaticLibs);
  1324. iblinkothersharedlibs :
  1325. readlinkcontainer(LinkotherSharedLibs);
  1326. iblinkotherframeworks :
  1327. readlinkcontainer(LinkOtherFrameworks);
  1328. ibmainname:
  1329. begin
  1330. mainname:=ppufile.getpshortstring;
  1331. if (mainaliasname<>defaultmainaliasname) then
  1332. Message1(scan_w_multiple_main_name_overrides,mainaliasname);
  1333. mainaliasname:=mainname^;
  1334. end;
  1335. ibImportSymbols :
  1336. readImportSymbols;
  1337. ibderefmap :
  1338. readderefmap;
  1339. ibderefdata :
  1340. readderefdata;
  1341. ibresources:
  1342. readResources;
  1343. iborderedsymbols:
  1344. readOrderedSymbols;
  1345. ibwpofile:
  1346. readwpofile;
  1347. ibendinterface :
  1348. break;
  1349. else
  1350. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1351. end;
  1352. { we can already stop when we know that we must recompile }
  1353. if do_compile then
  1354. exit;
  1355. until false;
  1356. end;
  1357. procedure tppumodule.load_implementation;
  1358. var
  1359. b : byte;
  1360. begin
  1361. { read implementation part }
  1362. repeat
  1363. b:=ppufile.readentry;
  1364. case b of
  1365. ibloadunit :
  1366. readloadunit;
  1367. ibasmsymbols :
  1368. readasmsyms;
  1369. ibunitimportsyms:
  1370. readunitimportsyms;
  1371. ibendimplementation :
  1372. break;
  1373. else
  1374. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1375. end;
  1376. until false;
  1377. end;
  1378. procedure tppumodule.writeppu;
  1379. begin
  1380. Message1(unit_u_ppu_write,realmodulename^);
  1381. { create unit flags }
  1382. {$ifdef cpufpemu}
  1383. if (cs_fp_emulation in current_settings.moduleswitches) then
  1384. headerflags:=headerflags or uf_fpu_emulation;
  1385. {$endif cpufpemu}
  1386. {$ifdef Test_Double_checksum_write}
  1387. Assign(CRCFile,s+'.IMP');
  1388. Rewrite(CRCFile);
  1389. {$endif def Test_Double_checksum_write}
  1390. { create new ppufile }
  1391. ppufile:=tcompilerppufile.create(ppufilename);
  1392. if not ppufile.createfile then
  1393. Message(unit_f_ppu_cannot_write);
  1394. { extra header (sub version, module flags) }
  1395. writeextraheader;
  1396. { first the (JVM) namespace }
  1397. if assigned(namespace) then
  1398. begin
  1399. ppufile.putstring(namespace^);
  1400. ppufile.writeentry(ibjvmnamespace);
  1401. end;
  1402. { the unitname }
  1403. ppufile.putstring(realmodulename^);
  1404. ppufile.writeentry(ibmodulename);
  1405. ppufile.putsmallset(moduleoptions);
  1406. if mo_has_deprecated_msg in moduleoptions then
  1407. ppufile.putstring(deprecatedmsg^);
  1408. ppufile.writeentry(ibmoduleoptions);
  1409. { write the alternate main procedure name if any }
  1410. if assigned(mainname) then
  1411. begin
  1412. ppufile.putstring(mainname^);
  1413. ppufile.writeentry(ibmainname);
  1414. end;
  1415. if cs_compilesystem in current_settings.moduleswitches then
  1416. begin
  1417. ppufile.putsmallset(features);
  1418. ppufile.writeentry(ibfeatures);
  1419. end;
  1420. writesourcefiles;
  1421. {$IFDEF MACRO_DIFF_HINT}
  1422. writeusedmacros;
  1423. {$ENDIF}
  1424. { write interface uses }
  1425. writeusedunit(true);
  1426. { write the objectfiles and libraries that come for this unit,
  1427. preserve the containers because they are still needed to load
  1428. the link.res.
  1429. All doesn't depend on the crc! It doesn't matter
  1430. if a unit is in a .o or .a file }
  1431. ppufile.do_crc:=false;
  1432. { write after source files, so that we know whether or not the compiler
  1433. will recompile the unit when checking whether the correct wpo file is
  1434. used (if it will recompile the unit anyway, it doesn't matter)
  1435. }
  1436. if (wpofeedbackinput<>'') then
  1437. begin
  1438. ppufile.putstring(wpofeedbackinput);
  1439. ppufile.putlongint(getnamedfiletime(wpofeedbackinput));
  1440. ppufile.writeentry(ibwpofile);
  1441. end;
  1442. writelinkcontainer(linkunitofiles,iblinkunitofiles,true);
  1443. writelinkcontainer(linkunitstaticlibs,iblinkunitstaticlibs,true);
  1444. writelinkcontainer(linkunitsharedlibs,iblinkunitsharedlibs,true);
  1445. writelinkcontainer(linkotherofiles,iblinkotherofiles,false);
  1446. writelinkcontainer(linkotherstaticlibs,iblinkotherstaticlibs,true);
  1447. writelinkcontainer(linkothersharedlibs,iblinkothersharedlibs,true);
  1448. writelinkcontainer(linkotherframeworks,iblinkotherframeworks,true);
  1449. writeImportSymbols;
  1450. writeResources;
  1451. writeOrderedSymbols;
  1452. ppufile.do_crc:=true;
  1453. { generate implementation deref data, the interface deref data is
  1454. already generated when calculating the interface crc }
  1455. if (cs_compilesystem in current_settings.moduleswitches) then
  1456. begin
  1457. tstoredsymtable(globalsymtable).buildderef;
  1458. derefdataintflen:=derefdata.size;
  1459. end
  1460. else
  1461. { the unit may have been re-resolved, in which case the current
  1462. position in derefdata is not necessarily at the end }
  1463. derefdata.seek(derefdata.size);
  1464. tstoredsymtable(globalsymtable).buildderefimpl;
  1465. tunitwpoinfo(wpoinfo).buildderef;
  1466. tunitwpoinfo(wpoinfo).buildderefimpl;
  1467. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1468. begin
  1469. tstoredsymtable(globalmacrosymtable).buildderef;
  1470. tstoredsymtable(globalmacrosymtable).buildderefimpl;
  1471. end;
  1472. if mf_local_symtable in moduleflags then
  1473. tstoredsymtable(localsymtable).buildderef_registered;
  1474. buildderefunitimportsyms;
  1475. writederefmap;
  1476. writederefdata;
  1477. ppufile.writeentry(ibendinterface);
  1478. { write the symtable entries }
  1479. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1480. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1481. begin
  1482. ppufile.putbyte(byte(true));
  1483. ppufile.writeentry(ibexportedmacros);
  1484. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1485. end
  1486. else
  1487. begin
  1488. ppufile.putbyte(byte(false));
  1489. ppufile.writeentry(ibexportedmacros);
  1490. end;
  1491. { everything after this doesn't affect the crc }
  1492. ppufile.do_crc:=false;
  1493. { write implementation uses }
  1494. writeusedunit(false);
  1495. { write all public assembler symbols }
  1496. writeasmsyms(ualt_public,publicasmsyms);
  1497. { write all external assembler symbols }
  1498. writeasmsyms(ualt_extern,externasmsyms);
  1499. { write all symbols imported from another unit }
  1500. writeunitimportsyms;
  1501. { end of implementation }
  1502. ppufile.writeentry(ibendimplementation);
  1503. { write static symtable
  1504. needed for local debugging of unit functions }
  1505. if mf_local_symtable in moduleflags then
  1506. tstoredsymtable(localsymtable).ppuwrite(ppufile);
  1507. { write whole program optimisation-related information }
  1508. tunitwpoinfo(wpoinfo).ppuwrite(ppufile);
  1509. { the last entry ibend is written automatically }
  1510. { flush to be sure }
  1511. ppufile.flush;
  1512. { create and write header }
  1513. ppufile.header.common.size:=ppufile.size;
  1514. ppufile.header.checksum:=ppufile.crc;
  1515. ppufile.header.interface_checksum:=ppufile.interface_crc;
  1516. ppufile.header.indirect_checksum:=ppufile.indirect_crc;
  1517. ppufile.header.common.compiler:=wordversion;
  1518. ppufile.header.common.cpu:=word(target_cpu);
  1519. ppufile.header.common.target:=word(target_info.system);
  1520. ppufile.header.common.flags:=headerflags;
  1521. ppufile.header.deflistsize:=current_module.deflist.count;
  1522. ppufile.header.symlistsize:=current_module.symlist.count;
  1523. ppufile.writeheader;
  1524. { save crc in current module also }
  1525. crc:=ppufile.crc;
  1526. interface_crc:=ppufile.interface_crc;
  1527. indirect_crc:=ppufile.indirect_crc;
  1528. {$ifdef Test_Double_checksum_write}
  1529. close(CRCFile);
  1530. {$endif Test_Double_checksum_write}
  1531. ppufile.closefile;
  1532. ppufile.free;
  1533. ppufile:=nil;
  1534. end;
  1535. procedure tppumodule.getppucrc;
  1536. begin
  1537. {$ifdef Test_Double_checksum_write}
  1538. Assign(CRCFile,s+'.INT')
  1539. Rewrite(CRCFile);
  1540. {$endif def Test_Double_checksum_write}
  1541. { create new ppufile }
  1542. ppufile:=tcompilerppufile.create(ppufilename);
  1543. ppufile.crc_only:=true;
  1544. if not ppufile.createfile then
  1545. Message(unit_f_ppu_cannot_write);
  1546. { first the (JVM) namespace }
  1547. if assigned(namespace) then
  1548. begin
  1549. ppufile.putstring(namespace^);
  1550. ppufile.writeentry(ibjvmnamespace);
  1551. end;
  1552. { the unitname }
  1553. ppufile.putstring(realmodulename^);
  1554. ppufile.writeentry(ibmodulename);
  1555. { extra header (sub version, module flags) }
  1556. writeextraheader;
  1557. ppufile.putsmallset(moduleoptions);
  1558. if mo_has_deprecated_msg in moduleoptions then
  1559. ppufile.putstring(deprecatedmsg^);
  1560. ppufile.writeentry(ibmoduleoptions);
  1561. { the interface units affect the crc }
  1562. writeusedunit(true);
  1563. { deref data of interface that affect the crc }
  1564. derefdata.reset;
  1565. tstoredsymtable(globalsymtable).buildderef;
  1566. derefdataintflen:=derefdata.size;
  1567. writederefmap;
  1568. writederefdata;
  1569. ppufile.writeentry(ibendinterface);
  1570. { write the symtable entries }
  1571. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1572. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1573. begin
  1574. ppufile.putbyte(byte(true));
  1575. ppufile.writeentry(ibexportedmacros);
  1576. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1577. end
  1578. else
  1579. begin
  1580. ppufile.putbyte(byte(false));
  1581. ppufile.writeentry(ibexportedmacros);
  1582. end;
  1583. { save crc }
  1584. crc:=ppufile.crc;
  1585. interface_crc:=ppufile.interface_crc;
  1586. indirect_crc:=ppufile.indirect_crc;
  1587. { end of implementation, to generate a correct ppufile
  1588. for ppudump when using INTFPPU define }
  1589. ppufile.writeentry(ibendimplementation);
  1590. {$ifdef Test_Double_checksum}
  1591. crc_array:=ppufile.crc_test;
  1592. ppufile.crc_test:=nil;
  1593. crc_size:=ppufile.crc_index2;
  1594. crc_array2:=ppufile.crc_test2;
  1595. ppufile.crc_test2:=nil;
  1596. crc_size2:=ppufile.crc_index2;
  1597. {$endif Test_Double_checksum}
  1598. {$ifdef Test_Double_checksum_write}
  1599. close(CRCFile);
  1600. {$endif Test_Double_checksum_write}
  1601. { create and write header, this will only be used
  1602. for debugging purposes }
  1603. ppufile.header.common.size:=ppufile.size;
  1604. ppufile.header.checksum:=ppufile.crc;
  1605. ppufile.header.interface_checksum:=ppufile.interface_crc;
  1606. ppufile.header.indirect_checksum:=ppufile.indirect_crc;
  1607. ppufile.header.common.compiler:=wordversion;
  1608. ppufile.header.common.cpu:=word(target_cpu);
  1609. ppufile.header.common.target:=word(target_info.system);
  1610. ppufile.header.common.flags:=headerflags;
  1611. ppufile.writeheader;
  1612. ppufile.closefile;
  1613. ppufile.free;
  1614. ppufile:=nil;
  1615. end;
  1616. procedure tppumodule.load_usedunits;
  1617. var
  1618. pu : tused_unit;
  1619. begin
  1620. if current_module<>self then
  1621. internalerror(200212284);
  1622. { load the used units from interface }
  1623. in_interface:=true;
  1624. pu:=tused_unit(used_units.first);
  1625. while assigned(pu) do
  1626. begin
  1627. if pu.in_interface then
  1628. begin
  1629. tppumodule(pu.u).loadppu;
  1630. { if this unit is compiled we can stop }
  1631. if state=ms_compiled then
  1632. exit;
  1633. { add this unit to the dependencies }
  1634. pu.u.adddependency(self);
  1635. { need to recompile the current unit, check the interface
  1636. crc. And when not compiled with -Ur then check the complete
  1637. crc }
  1638. if (pu.u.interface_crc<>pu.interface_checksum) or
  1639. (pu.u.indirect_crc<>pu.indirect_checksum) or
  1640. (
  1641. (not(mf_release in moduleflags)) and
  1642. (pu.u.crc<>pu.checksum)
  1643. ) then
  1644. begin
  1645. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename,@queuecomment);
  1646. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1647. if (pu.u.interface_crc<>pu.interface_checksum) then
  1648. writeln(' intfcrc change: ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1649. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1650. writeln(' indcrc change: ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
  1651. else
  1652. writeln(' implcrc change: ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
  1653. {$endif DEBUG_UNIT_CRC_CHANGES}
  1654. recompile_reason:=rr_crcchanged;
  1655. do_compile:=true;
  1656. exit;
  1657. end;
  1658. end;
  1659. pu:=tused_unit(pu.next);
  1660. end;
  1661. { ok, now load the interface of this unit }
  1662. if current_module<>self then
  1663. internalerror(200208187);
  1664. deflist.count:=ppufile.header.deflistsize;
  1665. symlist.count:=ppufile.header.symlistsize;
  1666. globalsymtable:=tglobalsymtable.create(modulename^,moduleid);
  1667. tstoredsymtable(globalsymtable).ppuload(ppufile);
  1668. if ppufile.readentry<>ibexportedmacros then
  1669. Message(unit_f_ppu_read_error);
  1670. if boolean(ppufile.getbyte) then
  1671. begin
  1672. globalmacrosymtable:=tmacrosymtable.Create(true);
  1673. tstoredsymtable(globalmacrosymtable).ppuload(ppufile)
  1674. end;
  1675. interface_compiled:=true;
  1676. { read the implementation part, containing
  1677. the implementation uses and ObjData }
  1678. in_interface:=false;
  1679. load_implementation;
  1680. { now only read the implementation uses }
  1681. pu:=tused_unit(used_units.first);
  1682. while assigned(pu) do
  1683. begin
  1684. if (not pu.in_interface) then
  1685. begin
  1686. tppumodule(pu.u).loadppu;
  1687. { if this unit is compiled we can stop }
  1688. if state=ms_compiled then
  1689. exit;
  1690. { add this unit to the dependencies }
  1691. pu.u.adddependency(self);
  1692. { need to recompile the current unit ? }
  1693. if (pu.u.interface_crc<>pu.interface_checksum) or
  1694. (pu.u.indirect_crc<>pu.indirect_checksum) then
  1695. begin
  1696. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename+' {impl}',@queuecomment);
  1697. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1698. if (pu.u.interface_crc<>pu.interface_checksum) then
  1699. writeln(' intfcrc change (2): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1700. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1701. writeln(' indcrc change (2): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8));
  1702. {$endif DEBUG_UNIT_CRC_CHANGES}
  1703. recompile_reason:=rr_crcchanged;
  1704. do_compile:=true;
  1705. exit;
  1706. end;
  1707. end;
  1708. pu:=tused_unit(pu.next);
  1709. end;
  1710. { load implementation symtable }
  1711. if mf_local_symtable in moduleflags then
  1712. begin
  1713. localsymtable:=tstaticsymtable.create(modulename^,moduleid);
  1714. tstaticsymtable(localsymtable).ppuload(ppufile);
  1715. end;
  1716. { we can now derefence all pointers to the implementation parts }
  1717. tstoredsymtable(globalsymtable).derefimpl(false);
  1718. { we've just loaded the localsymtable from the ppu file, so everything
  1719. in it was registered by definition (otherwise it wouldn't have been in
  1720. there) }
  1721. if assigned(localsymtable) then
  1722. tstoredsymtable(localsymtable).derefimpl(false);
  1723. derefunitimportsyms;
  1724. { read whole program optimisation-related information }
  1725. wpoinfo:=tunitwpoinfo.ppuload(ppufile);
  1726. tunitwpoinfo(wpoinfo).deref;
  1727. tunitwpoinfo(wpoinfo).derefimpl;
  1728. end;
  1729. function tppumodule.needrecompile:boolean;
  1730. var
  1731. pu : tused_unit;
  1732. begin
  1733. result:=false;
  1734. pu:=tused_unit(used_units.first);
  1735. while assigned(pu) do
  1736. begin
  1737. { need to recompile the current unit, check the interface
  1738. crc. And when not compiled with -Ur then check the complete
  1739. crc }
  1740. if (pu.u.interface_crc<>pu.interface_checksum) or
  1741. (pu.u.indirect_crc<>pu.indirect_checksum) or
  1742. (
  1743. (pu.in_interface) and
  1744. (pu.u.crc<>pu.checksum)
  1745. ) then
  1746. begin
  1747. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1748. if (pu.u.interface_crc<>pu.interface_checksum) then
  1749. writeln(' intfcrc change (3): ',hexstr(pu.u.interface_crc,8),' <> ',hexstr(pu.interface_checksum,8))
  1750. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1751. writeln(' indcrc change (3): ',hexstr(pu.u.indirect_crc,8),' <> ',hexstr(pu.indirect_checksum,8))
  1752. else
  1753. writeln(' implcrc change (3): ',hexstr(pu.u.crc,8),' <> ',hexstr(pu.checksum,8));
  1754. {$endif DEBUG_UNIT_CRC_CHANGES}
  1755. result:=true;
  1756. exit;
  1757. end;
  1758. pu:=tused_unit(pu.next);
  1759. end;
  1760. end;
  1761. procedure tppumodule.setdefgeneration;
  1762. begin
  1763. defsgeneration:=currentdefgeneration;
  1764. inc(currentdefgeneration);
  1765. end;
  1766. procedure tppumodule.reload_flagged_units;
  1767. var
  1768. hp : tppumodule;
  1769. begin
  1770. { now reload all dependent units with outdated defs }
  1771. hp:=tppumodule(loaded_units.first);
  1772. while assigned(hp) do
  1773. begin
  1774. if hp.do_reload and
  1775. (hp.defsgeneration<defsgeneration) then
  1776. begin
  1777. hp.defsgeneration:=defsgeneration;
  1778. hp.loadppu
  1779. end
  1780. else
  1781. hp.do_reload:=false;
  1782. hp:=tppumodule(hp.next);
  1783. end;
  1784. end;
  1785. procedure tppumodule.end_of_parsing;
  1786. begin
  1787. { module is now compiled }
  1788. state:=ms_compiled;
  1789. { free ppu }
  1790. if assigned(ppufile) then
  1791. begin
  1792. ppufile.free;
  1793. ppufile:=nil;
  1794. end;
  1795. inherited end_of_parsing;
  1796. end;
  1797. procedure tppumodule.loadppu;
  1798. const
  1799. ImplIntf : array[boolean] of string[15]=('implementation','interface');
  1800. var
  1801. do_load,
  1802. second_time : boolean;
  1803. old_current_module : tmodule;
  1804. pu : tused_unit;
  1805. begin
  1806. old_current_module:=current_module;
  1807. Message3(unit_u_load_unit,old_current_module.modulename^,
  1808. ImplIntf[old_current_module.in_interface],
  1809. modulename^);
  1810. { Update loaded_from to detect cycles }
  1811. loaded_from:=old_current_module;
  1812. { check if the globalsymtable is already available, but
  1813. we must reload when the do_reload flag is set }
  1814. if (not do_reload) and
  1815. assigned(globalsymtable) then
  1816. exit;
  1817. { reset }
  1818. do_load:=true;
  1819. second_time:=false;
  1820. set_current_module(self);
  1821. { try to load it as a package unit first }
  1822. if (packagelist.count>0) and loadfrompackage then
  1823. begin
  1824. do_load:=false;
  1825. do_reload:=false;
  1826. state:=ms_compiled;
  1827. { PPU is not needed anymore }
  1828. if assigned(ppufile) then
  1829. begin
  1830. ppufile.closefile;
  1831. ppufile.free;
  1832. ppufile:=nil;
  1833. end;
  1834. { add the unit to the used units list of the program }
  1835. usedunits.concat(tused_unit.create(self,true,false,nil));
  1836. end;
  1837. { A force reload }
  1838. if do_reload then
  1839. begin
  1840. Message(unit_u_forced_reload);
  1841. do_reload:=false;
  1842. { When the unit is already loaded or being loaded
  1843. we can maybe skip a complete reload/recompile }
  1844. if assigned(globalsymtable) and
  1845. (not needrecompile) then
  1846. begin
  1847. { When we don't have any data stored yet there
  1848. is nothing to resolve }
  1849. if interface_compiled then
  1850. begin
  1851. Message1(unit_u_reresolving_unit,modulename^);
  1852. tstoredsymtable(globalsymtable).deref(false);
  1853. tstoredsymtable(globalsymtable).derefimpl(false);
  1854. if assigned(localsymtable) then
  1855. begin
  1856. { we have only builderef(impl)'d the registered symbols of
  1857. the localsymtable -> also only deref those again }
  1858. tstoredsymtable(localsymtable).deref(true);
  1859. tstoredsymtable(localsymtable).derefimpl(true);
  1860. end;
  1861. if assigned(wpoinfo) then
  1862. begin
  1863. tunitwpoinfo(wpoinfo).deref;
  1864. tunitwpoinfo(wpoinfo).derefimpl;
  1865. end;
  1866. { We have to flag the units that depend on this unit even
  1867. though it didn't change, because they might also
  1868. indirectly depend on the unit that did change (e.g.,
  1869. in case rgobj, rgx86 and rgcpu have been compiled
  1870. already, and then rgobj is recompiled for some reason
  1871. -> rgx86 is re-reresolved, but the vmtentries of trgcpu
  1872. must also be re-resolved, because they will also contain
  1873. pointers to procdefs in the old trgobj (in case of a
  1874. recompile, all old defs are freed) }
  1875. flagdependent(old_current_module);
  1876. reload_flagged_units;
  1877. end
  1878. else
  1879. Message1(unit_u_skipping_reresolving_unit,modulename^);
  1880. do_load:=false;
  1881. end;
  1882. end;
  1883. if do_load then
  1884. begin
  1885. { loading the unit for a second time? }
  1886. if state=ms_registered then
  1887. state:=ms_load
  1888. else
  1889. begin
  1890. { try to load the unit a second time first }
  1891. Message1(unit_u_second_load_unit,modulename^);
  1892. Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
  1893. { Flag modules to reload }
  1894. flagdependent(old_current_module);
  1895. { Reset the module }
  1896. reset;
  1897. if state in [ms_compile,ms_second_compile] then
  1898. begin
  1899. Message1(unit_u_second_compile_unit,modulename^);
  1900. state:=ms_second_compile;
  1901. do_compile:=true;
  1902. end
  1903. else
  1904. state:=ms_second_load;
  1905. second_time:=true;
  1906. end;
  1907. { close old_current_ppu on system that are
  1908. short on file handles like DOS PM }
  1909. {$ifdef SHORT_ON_FILE_HANDLES}
  1910. if old_current_module.is_unit and
  1911. assigned(tppumodule(old_current_module).ppufile) then
  1912. tppumodule(old_current_module).ppufile.tempclose;
  1913. {$endif SHORT_ON_FILE_HANDLES}
  1914. { try to opening ppu, skip this when we already
  1915. know that we need to compile the unit }
  1916. if not do_compile then
  1917. begin
  1918. Message1(unit_u_loading_unit,modulename^);
  1919. search_unit_files(false);
  1920. if not do_compile then
  1921. begin
  1922. load_interface;
  1923. setdefgeneration;
  1924. if not do_compile then
  1925. begin
  1926. load_usedunits;
  1927. if not do_compile then
  1928. Message1(unit_u_finished_loading_unit,modulename^);
  1929. end;
  1930. end;
  1931. { PPU is not needed anymore }
  1932. if assigned(ppufile) then
  1933. begin
  1934. ppufile.closefile;
  1935. ppufile.free;
  1936. ppufile:=nil;
  1937. end;
  1938. end;
  1939. { Do we need to recompile the unit }
  1940. if do_compile then
  1941. begin
  1942. { recompile the unit or give a fatal error if sources not available }
  1943. if not(sources_avail) then
  1944. begin
  1945. search_unit_files(true);
  1946. if not(sources_avail) then
  1947. begin
  1948. printcomments;
  1949. if recompile_reason=rr_noppu then
  1950. begin
  1951. pu:=tused_unit(loaded_from.used_units.first);
  1952. while assigned(pu) do
  1953. begin
  1954. if pu.u=self then
  1955. break;
  1956. pu:=tused_unit(pu.next);
  1957. end;
  1958. if assigned(pu) and assigned(pu.unitsym) then
  1959. MessagePos2(pu.unitsym.fileinfo,unit_f_cant_find_ppu,realmodulename^,loaded_from.realmodulename^)
  1960. else
  1961. Message2(unit_f_cant_find_ppu,realmodulename^,loaded_from.realmodulename^);
  1962. end
  1963. else
  1964. Message1(unit_f_cant_compile_unit,realmodulename^);
  1965. end;
  1966. end;
  1967. { we found the sources, we do not need the verbose messages anymore }
  1968. if comments <> nil then
  1969. begin
  1970. comments.free;
  1971. comments:=nil;
  1972. end;
  1973. { Flag modules to reload }
  1974. flagdependent(old_current_module);
  1975. { Reset the module }
  1976. reset;
  1977. { compile this module }
  1978. if not(state in [ms_compile,ms_second_compile]) then
  1979. state:=ms_compile;
  1980. compile(mainsource);
  1981. setdefgeneration;
  1982. end
  1983. else
  1984. state:=ms_compiled;
  1985. if current_module<>self then
  1986. internalerror(200212282);
  1987. if in_interface then
  1988. internalerror(200212283);
  1989. { for a second_time recompile reload all dependent units,
  1990. for a first time compile register the unit _once_ }
  1991. if second_time then
  1992. reload_flagged_units
  1993. else
  1994. usedunits.concat(tused_unit.create(self,true,false,nil));
  1995. { reopen the old module }
  1996. {$ifdef SHORT_ON_FILE_HANDLES}
  1997. if old_current_module.is_unit and
  1998. assigned(tppumodule(old_current_module).ppufile) then
  1999. tppumodule(old_current_module).ppufile.tempopen;
  2000. {$endif SHORT_ON_FILE_HANDLES}
  2001. end;
  2002. { we are back, restore current_module }
  2003. set_current_module(old_current_module);
  2004. end;
  2005. {*****************************************************************************
  2006. RegisterUnit
  2007. *****************************************************************************}
  2008. function registerunit(callermodule:tmodule;const s : TIDString;const fn:string) : tppumodule;
  2009. var
  2010. ups : TIDString;
  2011. hp : tppumodule;
  2012. hp2 : tmodule;
  2013. begin
  2014. { Info }
  2015. ups:=upper(s);
  2016. { search all loaded units }
  2017. hp:=tppumodule(loaded_units.first);
  2018. while assigned(hp) do
  2019. begin
  2020. if hp.modulename^=ups then
  2021. begin
  2022. { only check for units. The main program is also
  2023. as a unit in the loaded_units list. We simply need
  2024. to ignore this entry (PFV) }
  2025. if hp.is_unit then
  2026. begin
  2027. { both units in interface ? }
  2028. if callermodule.in_interface and
  2029. hp.in_interface then
  2030. begin
  2031. { check for a cycle }
  2032. hp2:=callermodule.loaded_from;
  2033. while assigned(hp2) and (hp2<>hp) do
  2034. begin
  2035. if hp2.in_interface then
  2036. hp2:=hp2.loaded_from
  2037. else
  2038. hp2:=nil;
  2039. end;
  2040. if assigned(hp2) then
  2041. Message2(unit_f_circular_unit_reference,callermodule.realmodulename^,hp.realmodulename^);
  2042. end;
  2043. break;
  2044. end;
  2045. end;
  2046. { the next unit }
  2047. hp:=tppumodule(hp.next);
  2048. end;
  2049. { the unit is not in the loaded units,
  2050. we create an entry and register the unit }
  2051. if not assigned(hp) then
  2052. begin
  2053. Message1(unit_u_registering_new_unit,Upper(s));
  2054. hp:=tppumodule.create(callermodule,s,fn,true);
  2055. hp.loaded_from:=callermodule;
  2056. addloadedunit(hp);
  2057. end;
  2058. { return }
  2059. registerunit:=hp;
  2060. end;
  2061. end.