fppu.pas 109 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109
  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,fpchash,finput,fmodule,
  33. symbase,ppu,symtype;
  34. type
  35. { tppumodule }
  36. TAvailableUnitFile = (auPPU,auSrc);
  37. TAvailableUnitFiles = set of TAvailableUnitFile;
  38. tppumodule = class(tmodule)
  39. ppufile : tcompilerppufile; { the PPU file }
  40. sourcefn : TPathStr; { Source specified with "uses .. in '..'" }
  41. comments : TCmdStrList;
  42. nsprefix : TCmdStr; { Namespace prefix the unit was found with }
  43. {$ifdef EnableCTaskPPU}
  44. loadedfrommodule: tmodule;
  45. ppu_waitingfor_crc: boolean;
  46. class var cycle_stamp: dword;
  47. var
  48. cycle_search_stamp: dword;
  49. {$endif}
  50. {$ifdef Test_Double_checksum}
  51. interface_read_crc_index,
  52. interface_write_crc_index,
  53. indirect_read_crc_index,
  54. indirect_write_crc_index,
  55. implementation_read_crc_index,
  56. implementation_write_crc_index : cardinal;
  57. interface_crc_array,
  58. indirect_crc_array,
  59. implementation_crc_array : pointer;
  60. {$endif def Test_Double_checksum}
  61. constructor create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
  62. destructor destroy;override;
  63. function statestr: string; override;
  64. procedure reset(for_recompile: boolean);override;
  65. procedure re_resolve(loadfrom: tmodule);
  66. function openppufile:boolean;
  67. function openppustream(strm:TCStream):boolean;
  68. procedure getppucrc;
  69. procedure writeppu;
  70. function loadppu(from_module : tmodule) : boolean;
  71. {$ifdef EnableCTaskPPU}
  72. function continueloadppu : boolean;
  73. function canreload(out firstwaiting: tmodule): boolean;
  74. procedure reload;
  75. function ppuloadcancontinue(out firstwaiting: tmodule): boolean;
  76. function is_reload_needed(pu: tdependent_unit): boolean; override;
  77. procedure recompile_cycle;
  78. {$endif}
  79. procedure post_load_or_compile(from_module : tmodule; second_time: boolean);
  80. procedure discardppu;
  81. function needrecompile:boolean; // EnableCTaskPPU: remove
  82. procedure setdefgeneration;
  83. procedure reload_flagged_units; // EnableCTaskPPU: remove
  84. procedure end_of_parsing;override;
  85. private
  86. unitimportsymsderefs : tfplist;
  87. { Each time a unit's defs are (re)created, its defsgeneration is
  88. set to the value of a global counter, and the global counter is
  89. increased. We only reresolve its dependent units' defs in case
  90. they have been resolved only for an older generation, in order to
  91. avoid endless resolving loops in case of cyclic dependencies. }
  92. defsgeneration : longint;
  93. function check_loadfrompackage: boolean;
  94. procedure check_reload(from_module: tmodule; var do_load: boolean);
  95. function openppu(ppufiletime:longint):boolean;
  96. procedure prepare_second_load(from_module: tmodule); // EnableCTaskPPU: remove
  97. procedure recompile_from_sources(from_module: tmodule);
  98. function search_unit_files(loaded_from : tmodule; onlysource:boolean):TAvailableUnitFiles;
  99. function search_unit(loaded_from : tmodule; onlysource,shortname:boolean):TAvailableUnitFiles;
  100. function loadfrompackage:boolean;
  101. procedure load_interface;
  102. procedure load_implementation;
  103. function load_usedunits: boolean;
  104. {$ifdef EnableCTaskPPU}
  105. function load_usedunits_section: boolean;
  106. function ppu_check_used_crcs: boolean;
  107. {$endif}
  108. procedure printcomments;
  109. procedure queuecomment(const s:TMsgStr;v,w:longint);
  110. procedure buildderefunitimportsyms;
  111. procedure derefunitimportsyms;
  112. procedure freederefunitimportsyms;
  113. procedure try_load_ppufile(from_module: tmodule); // EnableCTaskPPU: remove
  114. procedure writesourcefiles;
  115. procedure writeusedunit(intf:boolean);
  116. procedure writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  117. procedure writederefmap;
  118. procedure writederefdata;
  119. procedure writeImportSymbols;
  120. procedure writeResources;
  121. procedure writeOrderedSymbols;
  122. procedure writeunitimportsyms;
  123. procedure writeasmsyms(kind:tunitasmlisttype;list:tfphashobjectlist);
  124. procedure writeextraheader;
  125. procedure readsourcefiles;
  126. procedure readloadunit;
  127. procedure readlinkcontainer(var p:tlinkcontainer);
  128. procedure readderefmap;
  129. procedure readderefdata;
  130. procedure readImportSymbols;
  131. procedure readResources;
  132. procedure readOrderedSymbols;
  133. procedure readwpofile;
  134. procedure readunitimportsyms;
  135. procedure readasmsyms;
  136. procedure readextraheader;
  137. {$IFDEF MACRO_DIFF_HINT}
  138. procedure writeusedmacro(p:TNamedIndexItem;arg:pointer);
  139. procedure writeusedmacros;
  140. procedure readusedmacros;
  141. {$ENDIF}
  142. end;
  143. function registerunit(callermodule:tmodule;const s : TIDString;const fn:string; out is_new:boolean) : tppumodule;
  144. implementation
  145. uses
  146. SysUtils,
  147. cfileutl,
  148. systems,version,options,
  149. symtable, symsym,
  150. wpoinfo,
  151. scanner,
  152. aasmbase,ogbase,
  153. parser,
  154. comphook,
  155. entfile,fpkg,fpcp;
  156. var
  157. currentdefgeneration: longint;
  158. {****************************************************************************
  159. TPPUMODULE
  160. ****************************************************************************}
  161. constructor tppumodule.create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
  162. begin
  163. inherited create(LoadedFrom,amodulename,afilename,_is_unit);
  164. ppufile:=nil;
  165. sourcefn:=afilename;
  166. unitimportsymsderefs:=tfplist.create;
  167. end;
  168. destructor tppumodule.destroy;
  169. begin
  170. discardppu;
  171. comments.free;
  172. comments:=nil;
  173. { all derefs allocated with new
  174. are dispose'd inside this method }
  175. freederefunitimportsyms;
  176. unitimportsymsderefs.free;
  177. unitimportsymsderefs:=nil;
  178. inherited Destroy;
  179. end;
  180. function tppumodule.statestr: string;
  181. begin
  182. Result:=inherited statestr;
  183. {$IFDEF EnableCTaskPPU}
  184. if state<>ms_load then exit;
  185. if ppu_waitingfor_crc then
  186. Result:=Result+',waitcrc'
  187. else if interface_compiled then
  188. Result:=Result+',interface_compiled'
  189. else
  190. Result:=Result+',waitintf';
  191. {$ENDIF}
  192. end;
  193. procedure tppumodule.reset(for_recompile : boolean);
  194. begin
  195. {$IFDEF EnableCTaskPPU}
  196. loadedfrommodule:=nil;
  197. ppu_waitingfor_crc:=false;
  198. {$ENDIF}
  199. inc(currentdefgeneration);
  200. discardppu;
  201. freederefunitimportsyms;
  202. unitimportsymsderefs.free;
  203. unitimportsymsderefs:=tfplist.create;
  204. inherited reset(for_recompile);
  205. end;
  206. procedure tppumodule.re_resolve(loadfrom: tmodule);
  207. begin
  208. Message1(unit_u_reresolving_unit,modulename^);
  209. if tstoredsymtable(globalsymtable).is_deref_built then
  210. tstoredsymtable(globalsymtable).deref(false);
  211. if tstoredsymtable(globalsymtable).is_derefimpl_built then
  212. tstoredsymtable(globalsymtable).derefimpl(false);
  213. if assigned(localsymtable) then
  214. begin
  215. { we have only builderef(impl)'d the registered symbols of
  216. the localsymtable -> also only deref those again }
  217. if tstoredsymtable(localsymtable).is_deref_built then
  218. tstoredsymtable(localsymtable).deref(true);
  219. if tstoredsymtable(localsymtable).is_derefimpl_built then
  220. tstoredsymtable(localsymtable).derefimpl(true);
  221. end;
  222. if assigned(wpoinfo) then
  223. begin
  224. tunitwpoinfo(wpoinfo).deref;
  225. tunitwpoinfo(wpoinfo).derefimpl;
  226. end;
  227. {$IFDEF EnableCTaskPPU}
  228. { all dependent units were already flagged recursively for reload }
  229. defsgeneration:=currentdefgeneration;
  230. {$ELSE}
  231. { We have to flag the units that depend on this unit even
  232. though it didn't change, because they might also
  233. indirectly depend on the unit that did change (e.g.,
  234. in case rgobj, rgx86 and rgcpu have been compiled
  235. already, and then rgobj is recompiled for some reason
  236. -> rgx86 is re-reresolved, but the vmtentries of trgcpu
  237. must also be re-resolved, because they will also contain
  238. pointers to procdefs in the old trgobj (in case of a
  239. recompile, all old defs are freed) }
  240. flagdependent(loadfrom);
  241. reload_flagged_units;
  242. {$ENDIF}
  243. end;
  244. procedure tppumodule.queuecomment(const s:TMsgStr;v,w:longint);
  245. begin
  246. if comments = nil then
  247. comments := TCmdStrList.create;
  248. comments.insert(s);
  249. end;
  250. procedure tppumodule.printcomments;
  251. var
  252. comment: string;
  253. begin
  254. if comments = nil then
  255. exit;
  256. { comments are inserted in reverse order }
  257. repeat
  258. comment := comments.getlast;
  259. if length(comment) = 0 then
  260. exit;
  261. do_comment(v_normal, comment);
  262. until false;
  263. end;
  264. function tppumodule.openppufile:boolean;
  265. var
  266. ppufiletime : longint;
  267. begin
  268. openppufile:=false;
  269. Message1(unit_t_ppu_loading,ppufilename,@queuecomment);
  270. { Get ppufile time (also check if the file exists) }
  271. ppufiletime:=getnamedfiletime(ppufilename);
  272. if ppufiletime=-1 then
  273. exit;
  274. { Open the ppufile }
  275. Message1(unit_u_ppu_name,ppufilename);
  276. ppufile:=tcompilerppufile.create(ppufilename);
  277. if not ppufile.openfile then
  278. begin
  279. discardppu;
  280. Message(unit_u_ppu_file_too_short);
  281. exit;
  282. end;
  283. result:=openppu(ppufiletime);
  284. end;
  285. function tppumodule.openppustream(strm:TCStream):boolean;
  286. begin
  287. result:=false;
  288. { Open the ppufile }
  289. Message1(unit_u_ppu_name,ppufilename);
  290. ppufile:=tcompilerppufile.create(ppufilename);
  291. if not ppufile.openstream(strm) then
  292. begin
  293. discardppu;
  294. Message(unit_u_ppu_file_too_short);
  295. exit;
  296. end;
  297. result:=openppu(-1);
  298. end;
  299. function tppumodule.openppu(ppufiletime:longint):boolean;
  300. function checkheader: boolean;
  301. var
  302. psi: psysteminfo;
  303. system_name: shortstring;
  304. begin
  305. result:=false;
  306. { check for a valid PPU file }
  307. if not ppufile.CheckPPUId then
  308. begin
  309. Message(unit_u_ppu_invalid_header);
  310. exit;
  311. end;
  312. { check for allowed PPU versions }
  313. if not (ppufile.getversion = CurrentPPUVersion) then
  314. begin
  315. Message1(unit_u_ppu_invalid_version,tostr(ppufile.getversion),@queuecomment);
  316. exit;
  317. end;
  318. { check the target processor }
  319. if tsystemcpu(ppufile.header.common.cpu)<>target_cpu then
  320. begin
  321. Message1(unit_u_ppu_invalid_processor,cpu2str[tsystemcpu(ppufile.header.common.cpu)],@queuecomment);
  322. exit;
  323. end;
  324. { check target }
  325. if tsystem(ppufile.header.common.target)<>target_info.system then
  326. begin
  327. psi:=targetinfos[tsystem(ppufile.header.common.target)];
  328. if assigned(psi) then
  329. system_name:=psi^.shortname
  330. else
  331. system_name:='invalid ('+tostr(ppufile.header.common.target)+')';
  332. Message1(unit_u_ppu_invalid_target,system_name,@queuecomment);
  333. exit;
  334. end;
  335. {$ifdef cpufpemu}
  336. { check if floating point emulation is on?
  337. fpu emulation isn't unit levelwise because it affects calling convention }
  338. if ((ppufile.header.common.flags and uf_fpu_emulation)<>0) <>
  339. (cs_fp_emulation in current_settings.moduleswitches) then
  340. begin
  341. Message(unit_u_ppu_invalid_fpumode,@queuecomment);
  342. exit;
  343. end;
  344. {$endif cpufpemu}
  345. result:=true;
  346. end;
  347. function checkextraheader: boolean;
  348. begin
  349. result:=false;
  350. if ppufile.readentry<>ibextraheader then
  351. begin
  352. Message(unit_u_ppu_invalid_header);
  353. exit;
  354. end;
  355. readextraheader;
  356. if (longversion<>CurrentPPULongVersion) or
  357. not ppufile.EndOfEntry then
  358. begin
  359. Message(unit_u_ppu_invalid_header);
  360. exit;
  361. end;
  362. {$ifdef i8086}
  363. { check i8086 memory model flags }
  364. if (mf_i8086_far_code in moduleflags) <>
  365. (current_settings.x86memorymodel in [mm_medium,mm_large,mm_huge]) then
  366. begin
  367. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  368. exit;
  369. end;
  370. if (mf_i8086_far_data in moduleflags) <>
  371. (current_settings.x86memorymodel in [mm_compact,mm_large]) then
  372. begin
  373. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  374. exit;
  375. end;
  376. if (mf_i8086_huge_data in moduleflags) <>
  377. (current_settings.x86memorymodel=mm_huge) then
  378. begin
  379. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  380. exit;
  381. end;
  382. if (mf_i8086_cs_equals_ds in moduleflags) <>
  383. (current_settings.x86memorymodel=mm_tiny) then
  384. begin
  385. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  386. exit;
  387. end;
  388. if (mf_i8086_ss_equals_ds in moduleflags) <>
  389. (current_settings.x86memorymodel in [mm_tiny,mm_small,mm_medium]) then
  390. begin
  391. Message(unit_u_ppu_invalid_memory_model,@queuecomment);
  392. exit;
  393. end;
  394. {$endif i8086}
  395. {$ifdef wasm}
  396. { check WebAssembly exceptions mode flag }
  397. if ((mf_wasm_no_exceptions in moduleflags) <>
  398. (ts_wasm_no_exceptions in current_settings.targetswitches)) or
  399. ((mf_wasm_bf_exceptions in moduleflags) <>
  400. (ts_wasm_bf_exceptions in current_settings.targetswitches)) or
  401. ((mf_wasm_exnref_exceptions in moduleflags) <>
  402. (ts_wasm_native_exnref_exceptions in current_settings.targetswitches)) or
  403. ((mf_wasm_native_exceptions in moduleflags) <>
  404. (ts_wasm_native_legacy_exceptions in current_settings.targetswitches)) then
  405. begin
  406. Message(unit_u_ppu_invalid_wasm_exceptions_mode,@queuecomment);
  407. exit;
  408. end;
  409. if (mf_wasm_threads in moduleflags) <>
  410. (ts_wasm_threads in current_settings.targetswitches) then
  411. begin
  412. Message(unit_u_ppu_wasm_threads_mismatch,@queuecomment);
  413. exit;
  414. end;
  415. {$endif}
  416. if {$ifdef symansistr}not{$endif}(mf_symansistr in moduleflags) then
  417. begin
  418. Message(unit_u_ppu_symansistr_mismatch,@queuecomment);
  419. exit;
  420. end;
  421. if {$ifdef llvm}not{$endif}(mf_llvm in moduleflags) then
  422. begin
  423. Message(unit_u_ppu_llvm_mismatch,@queuecomment);
  424. exit;
  425. end;
  426. result:=true;
  427. end;
  428. begin
  429. openppu:=false;
  430. if not checkheader or
  431. not checkextraheader then
  432. begin
  433. discardppu;
  434. exit;
  435. end;
  436. { Load values for easier access }
  437. headerflags:=ppufile.header.common.flags;
  438. crc:=ppufile.header.checksum;
  439. crc_final:=true;
  440. interface_crc:=ppufile.header.interface_checksum;
  441. indirect_crc:=ppufile.header.indirect_checksum;
  442. change_endian:=ppufile.change_endian;
  443. { Show Debug info }
  444. if ppufiletime<>-1 then
  445. Message1(unit_u_ppu_time,filetimestring(ppufiletime))
  446. else
  447. Message1(unit_u_ppu_time,'unknown');
  448. Message1(unit_u_ppu_flags,tostr(headerflags));
  449. Message1(unit_u_ppu_crc,hexstr(ppufile.header.checksum,8));
  450. Message1(unit_u_ppu_crc,hexstr(ppufile.header.interface_checksum,8)+' (intfc)');
  451. Message1(unit_u_ppu_crc,hexstr(ppufile.header.indirect_checksum,8)+' (indc)');
  452. Comment(V_used,'Number of definitions: '+tostr(ppufile.header.deflistsize));
  453. Comment(V_used,'Number of symbols: '+tostr(ppufile.header.symlistsize));
  454. openppu:=true;
  455. end;
  456. function tppumodule.search_unit_files(loaded_from : tmodule; onlysource:boolean):TAvailableUnitFiles;
  457. var
  458. found : TAvailableUnitFiles;
  459. begin
  460. found:=search_unit(loaded_from,onlysource,false);
  461. if (found=[]) and
  462. (ft83 in AllowedFilenameTransFormations) and
  463. (length(modulename^)>8) then
  464. found:=search_unit(loaded_from,onlysource,true);
  465. search_unit_files:=found;
  466. end;
  467. function tppumodule.search_unit(loaded_from : tmodule; onlysource,shortname:boolean):TAvailableUnitFiles;
  468. var
  469. singlepathstring,
  470. filename : TCmdStr;
  471. Function UnitExists(const ext:string;var foundfile:TCmdStr;const prefix:TCmdStr):boolean;
  472. var
  473. s : tcmdstr;
  474. begin
  475. if CheckVerbosity(V_Tried) then
  476. Message1(unit_t_unitsearch,Singlepathstring+filename+ext);
  477. s:=FileName+ext;
  478. if prefix<>'' then
  479. s:=prefix+'.'+s;
  480. UnitExists:=FindFile(s,Singlepathstring,true,foundfile);
  481. end;
  482. Function PPUSearchPath(const s,prefix:TCmdStr):boolean;
  483. var
  484. found : boolean;
  485. hs,
  486. newname : TCmdStr;
  487. begin
  488. Found:=false;
  489. singlepathstring:=FixPath(s,false);
  490. { Check for PPU file }
  491. Found:=UnitExists(target_info.unitext,hs,prefix);
  492. if Found then
  493. Begin
  494. SetFileName(hs,false);
  495. if prefix<>'' then
  496. begin
  497. newname:=prefix+'.'+realmodulename^;
  498. stringdispose(realmodulename);
  499. realmodulename:=stringdup(newname);
  500. stringdispose(modulename);
  501. modulename:=stringdup(upper(newname));
  502. end;
  503. Found:=openppufile;
  504. End;
  505. PPUSearchPath:=Found;
  506. end;
  507. Function SourceSearchPath(const s,prefix:TCmdStr):boolean;
  508. var
  509. found : boolean;
  510. hs,
  511. newname : TCmdStr;
  512. begin
  513. Found:=false;
  514. singlepathstring:=FixPath(s,false);
  515. { Check for Sources }
  516. ppufile:=nil;
  517. recompile_reason:=rr_noppu;
  518. {Check for .pp file}
  519. Found:=UnitExists(sourceext,hs,prefix);
  520. if not Found then
  521. begin
  522. { Check for .pas }
  523. Found:=UnitExists(pasext,hs,prefix);
  524. end;
  525. if not Found and
  526. ((m_mac in current_settings.modeswitches) or
  527. (tf_p_ext_support in target_info.flags)) then
  528. begin
  529. { Check for .p, if mode is macpas}
  530. Found:=UnitExists(pext,hs,prefix);
  531. end;
  532. mainsource:='';
  533. if Found then
  534. begin
  535. sources_avail:=true;
  536. { Load Filenames when found }
  537. mainsource:=hs;
  538. SetFileName(hs,false);
  539. if prefix<>'' then
  540. begin
  541. newname:=prefix+'.'+realmodulename^;
  542. stringdispose(realmodulename);
  543. realmodulename:=stringdup(newname);
  544. stringdispose(modulename);
  545. modulename:=stringdup(upper(newname));
  546. end;
  547. end
  548. else
  549. sources_avail:=false;
  550. SourceSearchPath:=Found;
  551. end;
  552. Function SearchPath(const s,prefix:TCmdStr):TAvailableUnitFiles;
  553. var
  554. found : TAvailableUnitFiles;
  555. begin
  556. { First check for a ppu, then for the source }
  557. found:=[];
  558. if not onlysource then
  559. if PPUSearchPath(s,prefix) then
  560. Include(found,auPPU);
  561. if found=[] then
  562. if SourceSearchPath(s,prefix) then
  563. Include(found,auSrc);
  564. SearchPath:=found;
  565. end;
  566. Function SearchPathList(list:TSearchPathList;const prefix:TCmdStr):TAvailableUnitFiles;
  567. var
  568. hp : TCmdStrListItem;
  569. found : TAvailableUnitFiles;
  570. begin
  571. found:=[];
  572. hp:=TCmdStrListItem(list.First);
  573. while assigned(hp) do
  574. begin
  575. found:=SearchPath(hp.Str,prefix);
  576. if found<>[] then
  577. break;
  578. hp:=TCmdStrListItem(hp.next);
  579. end;
  580. SearchPathList:=found;
  581. end;
  582. function SearchPPUPaths(const prefix:TCmdStr):boolean;
  583. begin
  584. result:=PPUSearchPath('.',prefix);
  585. if (not result) and (outputpath<>'') then
  586. result:=PPUSearchPath(outputpath,prefix);
  587. if (not result) and Assigned(main_module) and (main_module.Path<>'') then
  588. result:=PPUSearchPath(main_module.Path,prefix);
  589. end;
  590. function SearchSourcePaths(const prefix:TCmdStr):TAvailableUnitFiles;
  591. begin
  592. result:=[];
  593. if SourceSearchPath('.',prefix) then
  594. include(Result,auSrc);
  595. if (result=[]) and Assigned(main_module) and (main_module.Path<>'') then
  596. if SourceSearchPath(main_module.Path,prefix) then
  597. include(Result,auSrc);
  598. if (result=[]) and Assigned(loaded_from) then
  599. result:=SearchPathList(loaded_from.LocalUnitSearchPath,prefix);
  600. if (result=[]) then
  601. result:=SearchPathList(UnitSearchPath,prefix);
  602. end;
  603. function SearchNamespaceList(const prefixes:TCmdStrList): TAvailableUnitFiles;
  604. var
  605. nsitem : TCmdStrListItem;
  606. res : TAvailableUnitFiles;
  607. begin
  608. res:=[];
  609. nsitem:=TCmdStrListItem(prefixes.first);
  610. while assigned(nsitem) do
  611. begin
  612. if not onlysource then
  613. begin
  614. if SearchPPUPaths(nsitem.str) then
  615. Include(res,auPPU);
  616. if res<>[] then
  617. break;
  618. end;
  619. res:=SearchSourcePaths(nsitem.str);
  620. if res<>[] then
  621. break;
  622. nsitem:=TCmdStrListItem(nsitem.next);
  623. end;
  624. if assigned(nsitem) then
  625. nsprefix:=nsitem.str;
  626. result:=res;
  627. end;
  628. var
  629. fnd : TAvailableUnitFiles;
  630. hs : TPathStr;
  631. begin
  632. fnd:=[];
  633. if shortname then
  634. filename:=FixFileName(Copy(realmodulename^,1,8))
  635. else
  636. filename:=FixFileName(realmodulename^);
  637. { try to find unit
  638. 1. look for ppu in cwd
  639. 2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
  640. 3. look for ppu in maindir
  641. 4. look for the specified source file (from the uses line)
  642. 5. look for source in cwd
  643. 6. look for source in maindir
  644. 7. local unit pathlist
  645. 8. global unit pathlist
  646. 9. for each default namespace:
  647. repeat 1 - 3 and 5 - 8 with namespace as prefix }
  648. if not onlysource then
  649. if SearchPPUPaths('') then
  650. include(fnd,auPPU);
  651. if (fnd=[]) and (sourcefn<>'') then
  652. begin
  653. { the full filename is specified so we can't use here the
  654. searchpath (PFV) }
  655. if CheckVerbosity(V_Tried) then
  656. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,sourceext));
  657. if FindFile(ChangeFileExt(sourcefn,sourceext),'',true,hs) then
  658. include(fnd,auSrc);
  659. if (fnd=[]) then
  660. begin
  661. if CheckVerbosity(V_Tried) then
  662. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,pasext));
  663. if FindFile(ChangeFileExt(sourcefn,pasext),'',true,hs) then
  664. include(fnd,auSrc);
  665. end;
  666. if (fnd=[]) and
  667. ((m_mac in current_settings.modeswitches) or
  668. (tf_p_ext_support in target_info.flags)) then
  669. begin
  670. if CheckVerbosity(V_Tried) then
  671. Message1(unit_t_unitsearch,ChangeFileExt(sourcefn,pext));
  672. if FindFile(ChangeFileExt(sourcefn,pext),'',true,hs) then
  673. include(fnd,auSrc)
  674. end;
  675. if [auSrc]=fnd then
  676. begin
  677. sources_avail:=true;
  678. {$IFDEF DEBUG_PPU_CYCLES}
  679. writeln('PPUALGO tppumodule.search_unit only sources, no ppu -> ',modulename^,' old=',state,' new=',ms_compile);
  680. {$ENDIF}
  681. state:=ms_compile;
  682. recompile_reason:=rr_noppu;
  683. mainsource:=hs;
  684. SetFileName(hs,false);
  685. end;
  686. end;
  687. if fnd=[] then
  688. begin
  689. fnd:=SearchSourcePaths('');
  690. // current_namespacelist is set to the current module's namespacelist.
  691. if (fnd=[]) and assigned(current_namespacelist) and (current_namespacelist.count>0) then
  692. fnd:=SearchNameSpaceList(current_namespacelist);
  693. if (fnd=[]) and (namespacelist.count>0) then
  694. fnd:=SearchNameSpaceList(namespacelist);
  695. end;
  696. search_unit:=fnd;
  697. end;
  698. function tppumodule.loadfrompackage: boolean;
  699. (*var
  700. singlepathstring,
  701. filename : TCmdStr;
  702. Function UnitExists(const ext:string;var foundfile:TCmdStr):boolean;
  703. begin
  704. if CheckVerbosity(V_Tried) then
  705. Message1(unit_t_unitsearch,Singlepathstring+filename);
  706. UnitExists:=FindFile(FileName,Singlepathstring,true,foundfile);
  707. end;
  708. Function PPUSearchPath(const s:TCmdStr):boolean;
  709. var
  710. found : boolean;
  711. hs : TCmdStr;
  712. begin
  713. Found:=false;
  714. singlepathstring:=FixPath(s,false);
  715. { Check for PPU file }
  716. Found:=UnitExists(target_info.unitext,hs);
  717. if Found then
  718. Begin
  719. SetFileName(hs,false);
  720. //Found:=OpenPPU;
  721. End;
  722. PPUSearchPath:=Found;
  723. end;
  724. Function SearchPathList(list:TSearchPathList):boolean;
  725. var
  726. hp : TCmdStrListItem;
  727. found : boolean;
  728. begin
  729. found:=false;
  730. hp:=TCmdStrListItem(list.First);
  731. while assigned(hp) do
  732. begin
  733. found:=PPUSearchPath(hp.Str);
  734. if found then
  735. break;
  736. hp:=TCmdStrListItem(hp.next);
  737. end;
  738. SearchPathList:=found;
  739. end;*)
  740. var
  741. pkg : ppackageentry;
  742. pkgunit : pcontainedunit;
  743. i,idx : longint;
  744. strm : TCStream;
  745. begin
  746. result:=false;
  747. for i:=0 to packagelist.count-1 do
  748. begin
  749. pkg:=ppackageentry(packagelist[i]);
  750. if not assigned(pkg^.package) then
  751. internalerror(2013053103);
  752. idx:=pkg^.package.containedmodules.FindIndexOf(modulename^);
  753. if idx>=0 then
  754. begin
  755. { the unit is part of this package }
  756. pkgunit:=pcontainedunit(pkg^.package.containedmodules[idx]);
  757. if not assigned(pkgunit^.module) then
  758. pkgunit^.module:=self;
  759. { ToDo: check whether we really don't need this anymore }
  760. {filename:=pkgunit^.ppufile;
  761. if not SearchPathList(unitsearchpath) then
  762. exit};
  763. strm:=tpcppackage(pkg^.package).getmodulestream(self);
  764. if not assigned(strm) then
  765. internalerror(2015103002);
  766. if not openppustream(strm) then
  767. exit;
  768. package:=pkg^.package;
  769. Message2(unit_u_loading_from_package,modulename^,pkg^.package.packagename^);
  770. { now load the unit and all used units }
  771. load_interface;
  772. {$IFDEF EnableCTaskPPU}
  773. if not load_usedunits then
  774. internalerror(2026020415);
  775. {$ELSE}
  776. setdefgeneration;
  777. load_usedunits;
  778. {$ENDIF}
  779. Message1(unit_u_finished_loading_unit,modulename^);
  780. result:=true;
  781. break;
  782. end;
  783. end;
  784. end;
  785. procedure tppumodule.buildderefunitimportsyms;
  786. var
  787. i : longint;
  788. deref : pderef;
  789. begin
  790. unitimportsymsderefs.capacity:=unitimportsymsderefs.count+unitimportsyms.count;
  791. for i:=0 to unitimportsyms.count-1 do
  792. begin
  793. new(deref);
  794. deref^.build(unitimportsyms[i]);
  795. unitimportsymsderefs.add(deref);
  796. end;
  797. end;
  798. procedure tppumodule.derefunitimportsyms;
  799. var
  800. i : longint;
  801. sym : tsym;
  802. begin
  803. unitimportsyms.capacity:=unitimportsyms.count+unitimportsymsderefs.count;
  804. for i:=0 to unitimportsymsderefs.count-1 do
  805. begin
  806. sym:=tsym(pderef(unitimportsymsderefs[i])^.resolve);
  807. unitimportsyms.add(sym);
  808. end;
  809. end;
  810. procedure tppumodule.freederefunitimportsyms;
  811. var
  812. i : longint;
  813. deref : pderef;
  814. begin
  815. for i:=0 to unitimportsymsderefs.count-1 do
  816. begin
  817. deref:=pderef(unitimportsymsderefs[i]);
  818. system.dispose(deref);
  819. end;
  820. end;
  821. {**********************************
  822. PPU Reading/Writing Helpers
  823. ***********************************}
  824. {$IFDEF MACRO_DIFF_HINT}
  825. var
  826. is_initial: Boolean;
  827. procedure tppumodule.writeusedmacro(p:TNamedIndexItem;arg:pointer);
  828. begin
  829. if tmacro(p).is_used or is_initial then
  830. begin
  831. ppufile.putstring(p.name);
  832. ppufile.putboolean(is_initial);
  833. ppufile.putboolean(tmacro(p).is_used);
  834. end;
  835. end;
  836. procedure tppumodule.writeusedmacros;
  837. var
  838. oldcrc : boolean;
  839. begin
  840. oldcrc:=ppufile.do_crc;
  841. ppufile.do_crc:=false;
  842. is_initial:= true;
  843. initialmacrosymtable.foreach(@writeusedmacro,nil);
  844. is_initial:= false;
  845. if assigned(globalmacrosymtable) then
  846. globalmacrosymtable.foreach(@writeusedmacro,nil);
  847. localmacrosymtable.foreach(@writeusedmacro,nil);
  848. ppufile.writeentry(ibusedmacros);
  849. ppufile.do_crc:=oldcrc;
  850. end;
  851. {$ENDIF}
  852. procedure tppumodule.writesourcefiles;
  853. var
  854. hp : tinputfile;
  855. ifile : sizeint;
  856. oldcrc : boolean;
  857. begin
  858. { write the used source files }
  859. oldcrc:=ppufile.do_crc;
  860. ppufile.do_crc:=false;
  861. { write source files directly in good order }
  862. for ifile:=0 to sourcefiles.nfiles-1 do
  863. begin
  864. hp:=sourcefiles.files[ifile];
  865. ppufile.putstring(hp.inc_path+hp.name);
  866. ppufile.putlongint(hp.getfiletime);
  867. end;
  868. ppufile.writeentry(ibsourcefiles);
  869. ppufile.do_crc:=oldcrc;
  870. end;
  871. procedure tppumodule.writeusedunit(intf:boolean);
  872. var
  873. hp : tused_unit;
  874. oldcrc : boolean;
  875. u: tmodule;
  876. begin
  877. { write a reference for each used unit }
  878. {$IFDEF Debug_WaitCRC}
  879. writeln('tppumodule.writeusedunit START ',realmodulename^,' intf=',intf);
  880. {$ENDIF}
  881. {$IFDEF Debug_IndirectCRC}
  882. if intf then
  883. writeln('INDIRECT_CRC tppumodule.writeusedunit ',hexstr(ppufile.indirect_crc,8));
  884. {$ENDIF}
  885. hp:=tused_unit(used_units.first);
  886. while assigned(hp) do
  887. begin
  888. if hp.in_interface=intf then
  889. begin
  890. u:=hp.u;
  891. ppufile.putstring(u.realmodulename^);
  892. { the checksum should not affect the crc of this unit ! (PFV) }
  893. oldcrc:=ppufile.do_crc;
  894. ppufile.do_crc:=false;
  895. {$IFDEF Debug_WaitCRC}
  896. writeln('tppumodule.writeusedunit ',u.realmodulename^,' crc=',hexstr(u.crc,8),' interface_crc=',hexstr(u.interface_crc,8),' indirect_crc=',hexstr(u.indirect_crc,8));
  897. {$ENDIF}
  898. hp.checksum:=u.crc;
  899. hp.interface_checksum:=u.interface_crc;
  900. hp.indirect_checksum:=u.indirect_crc;
  901. ppufile.putlongint(longint(hp.checksum));
  902. ppufile.putlongint(longint(hp.interface_checksum));
  903. ppufile.putlongint(longint(hp.indirect_checksum));
  904. ppufile.do_crc:=oldcrc;
  905. { Combine all indirect checksums from units used by this unit.
  906. The indirect_crc contains the classes+records of this unit as well. }
  907. if intf then
  908. ppufile.indirect_crc:=UpdateCrc32(ppufile.indirect_crc,u.indirect_crc,sizeof(u.indirect_crc));
  909. {$IFDEF Debug_IndirectCRC}
  910. if intf then
  911. writeln('INDIRECT_CRC tppumodule.writeusedunit ',hexstr(ppufile.indirect_crc,8),' ',u.modulename^,' ',hexstr(u.indirect_crc,8),' ');
  912. {$ENDIF}
  913. end;
  914. hp:=tused_unit(hp.next);
  915. end;
  916. ppufile.writeentry(ibloadunit);
  917. end;
  918. procedure tppumodule.writelinkcontainer(var p:tlinkcontainer;id:byte;strippath:boolean);
  919. var
  920. hcontainer : tlinkcontainer;
  921. s : TPathStr;
  922. mask : cardinal;
  923. begin
  924. hcontainer:=TLinkContainer.Create;
  925. while not p.empty do
  926. begin
  927. s:=p.get(mask);
  928. if strippath then
  929. ppufile.putstring(ExtractFileName(s))
  930. else
  931. ppufile.putstring(s);
  932. ppufile.putlongint(mask);
  933. hcontainer.add(s,mask);
  934. end;
  935. ppufile.writeentry(id);
  936. p.Free;
  937. p:=hcontainer;
  938. end;
  939. procedure tppumodule.writederefmap;
  940. var
  941. i : longint;
  942. oldcrc : boolean;
  943. begin
  944. { This does not influence crc }
  945. oldcrc:=ppufile.do_crc;
  946. ppufile.do_crc:=false;
  947. { The unit map used for resolving }
  948. ppufile.putlongint(derefmapcnt);
  949. for i:=0 to derefmapcnt-1 do
  950. begin
  951. if not assigned(derefmap[i].u) then
  952. internalerror(2005011512);
  953. ppufile.putstring(derefmap[i].u.modulename^)
  954. end;
  955. ppufile.writeentry(ibderefmap);
  956. ppufile.do_crc:=oldcrc;
  957. end;
  958. procedure tppumodule.writederefdata;
  959. var
  960. oldcrc : boolean;
  961. len,hlen : longint;
  962. buf : array[0..1023] of byte;
  963. begin
  964. if longword(derefdataintflen)>derefdata.size then
  965. internalerror(200310223);
  966. derefdata.seek(0);
  967. { Write interface data }
  968. len:=derefdataintflen;
  969. while (len>0) do
  970. begin
  971. if len>1024 then
  972. hlen:=1024
  973. else
  974. hlen:=len;
  975. derefdata.read(buf,hlen);
  976. ppufile.putdata(buf,hlen);
  977. dec(len,hlen);
  978. end;
  979. { Write implementation data, this does not influence crc }
  980. oldcrc:=ppufile.do_crc;
  981. ppufile.do_crc:=false;
  982. len:=derefdata.size-derefdataintflen;
  983. while (len>0) do
  984. begin
  985. if len>1024 then
  986. hlen:=1024
  987. else
  988. hlen:=len;
  989. derefdata.read(buf,hlen);
  990. ppufile.putdata(buf,hlen);
  991. dec(len,hlen);
  992. end;
  993. if derefdata.pos<>derefdata.size then
  994. internalerror(200310224);
  995. ppufile.do_crc:=oldcrc;
  996. ppufile.writeentry(ibderefdata);
  997. end;
  998. procedure tppumodule.writeImportSymbols;
  999. var
  1000. i,j : longint;
  1001. ImportLibrary : TImportLibrary;
  1002. ImportSymbol : TImportSymbol;
  1003. begin
  1004. for i:=0 to ImportLibraryList.Count-1 do
  1005. begin
  1006. ImportLibrary:=TImportLibrary(ImportLibraryList[i]);
  1007. ppufile.putstring(ImportLibrary.Name);
  1008. ppufile.putlongint(ImportLibrary.ImportSymbolList.Count);
  1009. for j:=0 to ImportLibrary.ImportSymbolList.Count-1 do
  1010. begin
  1011. ImportSymbol:=TImportSymbol(ImportLibrary.ImportSymbolList[j]);
  1012. ppufile.putstring(ImportSymbol.Name);
  1013. ppufile.putstring(ImportSymbol.MangledName);
  1014. ppufile.putlongint(ImportSymbol.OrdNr);
  1015. ppufile.putbyte(byte(ImportSymbol.IsVar));
  1016. end;
  1017. end;
  1018. ppufile.writeentry(ibImportSymbols);
  1019. end;
  1020. procedure tppumodule.writeResources;
  1021. var
  1022. res : TCmdStrListItem;
  1023. begin
  1024. res:=TCmdStrListItem(ResourceFiles.First);
  1025. while res<>nil do
  1026. begin
  1027. ppufile.putstring(res.FPStr);
  1028. res:=TCmdStrListItem(res.Next);
  1029. end;
  1030. ppufile.writeentry(ibresources);
  1031. end;
  1032. procedure tppumodule.writeOrderedSymbols;
  1033. var
  1034. res : TCmdStrListItem;
  1035. begin
  1036. res:=TCmdStrListItem(linkorderedsymbols.First);
  1037. while res<>nil do
  1038. begin
  1039. ppufile.putstring(res.FPStr);
  1040. res:=TCmdStrListItem(res.Next);
  1041. end;
  1042. ppufile.writeentry(iborderedsymbols);
  1043. end;
  1044. procedure tppumodule.writeunitimportsyms;
  1045. var
  1046. i : longint;
  1047. begin
  1048. ppufile.putlongint(unitimportsymsderefs.count);
  1049. for i:=0 to unitimportsymsderefs.count-1 do
  1050. ppufile.putderef(pderef(unitimportsymsderefs[i])^);
  1051. ppufile.writeentry(ibunitimportsyms);
  1052. end;
  1053. procedure tppumodule.writeasmsyms(kind:tunitasmlisttype;list:tfphashobjectlist);
  1054. var
  1055. i : longint;
  1056. sym : TAsmSymbol;
  1057. begin
  1058. ppufile.putbyte(ord(kind));
  1059. ppufile.putlongint(list.count);
  1060. for i:=0 to list.count-1 do
  1061. begin
  1062. sym:=TAsmSymbol(list[i]);
  1063. ppufile.putstring(sym.Name);
  1064. ppufile.putbyte(ord(sym.bind));
  1065. ppufile.putbyte(ord(sym.typ));
  1066. end;
  1067. ppufile.writeentry(ibasmsymbols);
  1068. end;
  1069. procedure tppumodule.writeextraheader;
  1070. var
  1071. old_docrc: boolean;
  1072. begin
  1073. { create unit flags }
  1074. if do_release then
  1075. include(moduleflags,mf_release);
  1076. if assigned(localsymtable) then
  1077. include(moduleflags,mf_local_symtable);
  1078. if cs_checkpointer_called in current_settings.moduleswitches then
  1079. include(moduleflags,mf_checkpointer_called);
  1080. if cs_compilesystem in current_settings.moduleswitches then
  1081. include(moduleflags,mf_system_unit);
  1082. {$ifdef i8086}
  1083. if current_settings.x86memorymodel in [mm_medium,mm_large,mm_huge] then
  1084. include(moduleflags,mf_i8086_far_code);
  1085. if current_settings.x86memorymodel in [mm_compact,mm_large] then
  1086. include(moduleflags,mf_i8086_far_data);
  1087. if current_settings.x86memorymodel=mm_huge then
  1088. include(moduleflags,mf_i8086_huge_data);
  1089. if current_settings.x86memorymodel=mm_tiny then
  1090. include(moduleflags,mf_i8086_cs_equals_ds);
  1091. if current_settings.x86memorymodel in [mm_tiny,mm_small,mm_medium] then
  1092. include(moduleflags,mf_i8086_ss_equals_ds);
  1093. {$endif i8086}
  1094. {$ifdef wasm}
  1095. if ts_wasm_no_exceptions in current_settings.targetswitches then
  1096. include(moduleflags,mf_wasm_no_exceptions);
  1097. if ts_wasm_native_exnref_exceptions in current_settings.targetswitches then
  1098. include(moduleflags,mf_wasm_exnref_exceptions);
  1099. if ts_wasm_native_legacy_exceptions in current_settings.targetswitches then
  1100. include(moduleflags,mf_wasm_native_exceptions);
  1101. if ts_wasm_bf_exceptions in current_settings.targetswitches then
  1102. include(moduleflags,mf_wasm_bf_exceptions);
  1103. if ts_wasm_threads in current_settings.targetswitches then
  1104. include(moduleflags,mf_wasm_threads);
  1105. {$endif wasm}
  1106. {$ifdef llvm}
  1107. include(moduleflags,mf_llvm);
  1108. {$endif}
  1109. {$ifdef symansistr}
  1110. include(moduleflags,mf_symansistr);
  1111. {$endif}
  1112. old_docrc:=ppufile.do_crc;
  1113. ppufile.do_crc:=false;
  1114. ppufile.putlongint(longint(CurrentPPULongVersion));
  1115. ppufile.putset(tppuset4(moduleflags));
  1116. ppufile.writeentry(ibextraheader);
  1117. ppufile.do_crc:=old_docrc;
  1118. end;
  1119. {$IFDEF MACRO_DIFF_HINT}
  1120. {
  1121. Define MACRO_DIFF_HINT for the whole compiler (and ppudump)
  1122. to turn this facility on. Also the hint messages defined
  1123. below must be commented in in the msg/errore.msg file.
  1124. There is some problems with this, thats why it is shut off:
  1125. At the first compilation, consider a macro which is not initially
  1126. defined, but it is used (e g the check that it is undefined is true).
  1127. Since it do not exist, there is no macro object where the is_used
  1128. flag can be set. Later on when the macro is defined, and the ppu
  1129. is opened, the check cannot detect this.
  1130. Also, in which macro object should this flag be set ? It cant be set
  1131. for macros in the initialmacrosymboltable since this table is shared
  1132. between different files.
  1133. }
  1134. procedure tppumodule.readusedmacros;
  1135. var
  1136. hs : string;
  1137. mac : tmacro;
  1138. was_initial,
  1139. was_used : boolean;
  1140. {Reads macros which was defined or used when the module was compiled.
  1141. This is done when a ppu file is open, before it possibly is parsed.}
  1142. begin
  1143. while not ppufile.endofentry do
  1144. begin
  1145. hs:=ppufile.getstring;
  1146. was_initial:=ppufile.getboolean;
  1147. was_used:=ppufile.getboolean;
  1148. mac:=tmacro(initialmacrosymtable.Find(hs));
  1149. if assigned(mac) then
  1150. begin
  1151. {$ifndef EXTDEBUG}
  1152. { if we don't have the sources why tell }
  1153. if sources_avail then
  1154. {$endif ndef EXTDEBUG}
  1155. if (not was_initial) and was_used then
  1156. Message2(unit_h_cond_not_set_in_last_compile,hs,mainsource^);
  1157. end
  1158. else { not assigned }
  1159. if was_initial and
  1160. was_used then
  1161. Message2(unit_h_cond_set_in_last_compile,hs,mainsource^);
  1162. end;
  1163. end;
  1164. {$ENDIF}
  1165. procedure tppumodule.readsourcefiles;
  1166. var
  1167. temp,hs : string;
  1168. inc_path : string;
  1169. temp_dir : TCmdStr;
  1170. main_dir : TCmdStr;
  1171. found,
  1172. is_main : boolean;
  1173. orgfiletime,
  1174. source_time : longint;
  1175. hp : tinputfile;
  1176. begin
  1177. sources_avail:=not(mf_release in moduleflags);
  1178. is_main:=true;
  1179. main_dir:='';
  1180. while not ppufile.endofentry do
  1181. begin
  1182. hs:=SetDirSeparators(ppufile.getstring);
  1183. inc_path:=ExtractFilePath(hs);
  1184. orgfiletime:=ppufile.getlongint;
  1185. temp_dir:='';
  1186. if sources_avail then
  1187. begin
  1188. if (headerflags and uf_in_library)<>0 then
  1189. begin
  1190. sources_avail:=false;
  1191. temp:=' library';
  1192. end
  1193. else if pos('Macro ',hs)=1 then
  1194. begin
  1195. { we don't want to find this file }
  1196. { but there is a problem with file indexing !! }
  1197. temp:='';
  1198. end
  1199. else
  1200. begin
  1201. { check the date of the source files:
  1202. 1 path of sourcefn
  1203. 2 path of ppu
  1204. 3 path of main source
  1205. 4 current dir
  1206. 5 include/unit path }
  1207. found:=false;
  1208. if sourcefn<>'' then
  1209. begin
  1210. temp_dir:=ExtractFilePath(SetDirSeparators(sourcefn));
  1211. Source_Time:=GetNamedFileTime(temp_dir+hs);
  1212. if Source_Time<>-1 then
  1213. hs:=temp_dir+hs;
  1214. end else
  1215. Source_Time:=-1;
  1216. if Source_Time=-1 then
  1217. begin
  1218. Source_Time:=GetNamedFileTime(path+hs);
  1219. if Source_Time<>-1 then
  1220. hs:=path+hs
  1221. else
  1222. if not(is_main) then
  1223. begin
  1224. Source_Time:=GetNamedFileTime(main_dir+hs);
  1225. if Source_Time<>-1 then
  1226. hs:=main_dir+hs;
  1227. end;
  1228. end;
  1229. if Source_Time=-1 then
  1230. Source_Time:=GetNamedFileTime(hs);
  1231. if (Source_Time=-1) then
  1232. begin
  1233. if is_main then
  1234. found:=unitsearchpath.FindFile(hs,true,temp_dir)
  1235. else
  1236. found:=includesearchpath.FindFile(hs,true,temp_dir);
  1237. if found then
  1238. begin
  1239. Source_Time:=GetNamedFileTime(temp_dir);
  1240. if Source_Time<>-1 then
  1241. hs:=temp_dir;
  1242. end;
  1243. end;
  1244. if Source_Time<>-1 then
  1245. begin
  1246. if is_main then
  1247. main_dir:=ExtractFilePath(hs);
  1248. temp:=' time '+filetimestring(source_time);
  1249. if (orgfiletime<>-1) and
  1250. (source_time<>orgfiletime) then
  1251. begin
  1252. {$IFDEF DEBUG_PPU_CYCLES}
  1253. writeln('PPUALGO tppumodule.readsourcefiles sourcechanged ',modulename^,' old=',state,' new=',ms_compile);
  1254. {$ENDIF}
  1255. state:=ms_compile;
  1256. recompile_reason:=rr_sourcenewer;
  1257. Message2(unit_u_source_modified,hs,ppufilename,@queuecomment);
  1258. temp:=temp+' *';
  1259. end;
  1260. end
  1261. else
  1262. begin
  1263. sources_avail:=false;
  1264. temp:=' not found';
  1265. end;
  1266. hp:=tdosinputfile.create(hs);
  1267. hp.inc_path:=inc_path;
  1268. { the indexing is wrong here PM }
  1269. sourcefiles.register_file(hp);
  1270. end;
  1271. end
  1272. else
  1273. begin
  1274. { still register the source module for proper error messages
  1275. since source_avail for the module is still false, this should not hurt }
  1276. sourcefiles.register_file(tdosinputfile.create(hs));
  1277. temp:=' not available';
  1278. end;
  1279. if is_main then
  1280. begin
  1281. mainsource:=hs;
  1282. end;
  1283. Message1(unit_u_ppu_source,hs+temp,@queuecomment);
  1284. is_main:=false;
  1285. end;
  1286. { check if we want to rebuild every unit, only if the sources are
  1287. available }
  1288. if do_build and sources_avail then
  1289. begin
  1290. {$IFDEF DEBUG_PPU_CYCLES}
  1291. writeln('PPUALGO tppumodule.readsourcefiles do_build ',modulename^,' old=',state,' new=',ms_compile);
  1292. {$ENDIF}
  1293. state:=ms_compile;
  1294. recompile_reason:=rr_build;
  1295. end;
  1296. end;
  1297. procedure tppumodule.readloadunit;
  1298. var
  1299. hs : string;
  1300. pu : tused_unit;
  1301. hp : tppumodule;
  1302. indchecksum,
  1303. intfchecksum,
  1304. checksum : cardinal;
  1305. isnew : boolean;
  1306. begin
  1307. while not ppufile.endofentry do
  1308. begin
  1309. hs:=ppufile.getstring;
  1310. checksum:=cardinal(ppufile.getlongint);
  1311. intfchecksum:=cardinal(ppufile.getlongint);
  1312. indchecksum:=cardinal(ppufile.getlongint);
  1313. { set the state of this unit before registering, this is
  1314. needed for a correct circular dependency check }
  1315. hp:=registerunit(self,hs,'',isnew);
  1316. if isnew then
  1317. usedunits.Concat(tused_unit.create(hp,in_interface,true,nil));
  1318. if LoadCount=1 then
  1319. pu:=addusedunit(hp,false,nil)
  1320. else
  1321. begin
  1322. pu:=findusedunit(hp);
  1323. { Safety, normally this should not happen:
  1324. The used units list cannot change between loads unless recompiled and then loadcount is 1... }
  1325. if pu=nil then
  1326. pu:=addusedunit(hp,false,nil);
  1327. end;
  1328. pu.checksum:=checksum;
  1329. pu.interface_checksum:=intfchecksum;
  1330. pu.indirect_checksum:=indchecksum;
  1331. end;
  1332. in_interface:=false;
  1333. end;
  1334. procedure tppumodule.readlinkcontainer(var p:tlinkcontainer);
  1335. var
  1336. s : string;
  1337. m : longint;
  1338. begin
  1339. while not ppufile.endofentry do
  1340. begin
  1341. s:=ppufile.getstring;
  1342. m:=ppufile.getlongint;
  1343. p.add(s,m);
  1344. end;
  1345. end;
  1346. procedure tppumodule.readderefmap;
  1347. var
  1348. i : longint;
  1349. begin
  1350. { Load unit map used for resolving }
  1351. derefmapsize:=ppufile.getlongint;
  1352. derefmapcnt:=derefmapsize;
  1353. setlength(derefmap,derefmapsize);
  1354. for i:=0 to derefmapsize-1 do
  1355. derefmap[i].modulename:=ppufile.getpshortstring;
  1356. end;
  1357. procedure tppumodule.readderefdata;
  1358. var
  1359. len,hlen : longint;
  1360. buf : array[0..1023] of byte;
  1361. begin
  1362. len:=ppufile.entrysize;
  1363. while (len>0) do
  1364. begin
  1365. if len>1024 then
  1366. hlen:=1024
  1367. else
  1368. hlen:=len;
  1369. ppufile.getdata(buf,hlen);
  1370. derefdata.write(buf,hlen);
  1371. dec(len,hlen);
  1372. end;
  1373. end;
  1374. procedure tppumodule.readImportSymbols;
  1375. var
  1376. j,
  1377. extsymcnt : longint;
  1378. ImportLibrary : TImportLibrary;
  1379. extsymname : string;
  1380. extsymmangledname : string;
  1381. extsymordnr : longint;
  1382. extsymisvar : boolean;
  1383. begin
  1384. while not ppufile.endofentry do
  1385. begin
  1386. ImportLibrary:=TImportLibrary.Create(ImportLibraryList,ppufile.getstring);
  1387. extsymcnt:=ppufile.getlongint;
  1388. for j:=0 to extsymcnt-1 do
  1389. begin
  1390. extsymname:=ppufile.getstring;
  1391. extsymmangledname:=ppufile.getstring;
  1392. extsymordnr:=ppufile.getlongint;
  1393. extsymisvar:=(ppufile.getbyte<>0);
  1394. TImportSymbol.Create(ImportLibrary.ImportSymbolList,extsymname,
  1395. extsymmangledname,extsymordnr,extsymisvar);
  1396. end;
  1397. end;
  1398. end;
  1399. procedure tppumodule.readResources;
  1400. begin
  1401. while not ppufile.endofentry do
  1402. resourcefiles.Insert(ppufile.getstring);
  1403. end;
  1404. procedure tppumodule.readOrderedSymbols;
  1405. begin
  1406. while not ppufile.endofentry do
  1407. linkorderedsymbols.Concat(ppufile.getstring);
  1408. end;
  1409. procedure tppumodule.readwpofile;
  1410. var
  1411. orgwpofilename: string;
  1412. orgwpofiletime: longint;
  1413. begin
  1414. { check whether we are using the same wpo feedback input file as when
  1415. this unit was compiled (same file name and file date)
  1416. }
  1417. orgwpofilename:=ppufile.getstring;
  1418. orgwpofiletime:=ppufile.getlongint;
  1419. if (extractfilename(orgwpofilename)<>extractfilename(wpofeedbackinput)) or
  1420. (orgwpofiletime<>GetNamedFileTime(orgwpofilename)) then
  1421. { make sure we don't throw away a precompiled unit if the user simply
  1422. forgot to specify the right wpo feedback file
  1423. }
  1424. message3(unit_e_different_wpo_file,ppufilename,orgwpofilename,filetimestring(orgwpofiletime));
  1425. end;
  1426. procedure tppumodule.readunitimportsyms;
  1427. var
  1428. c,i : longint;
  1429. deref : pderef;
  1430. begin
  1431. c:=ppufile.getlongint;
  1432. for i:=0 to c-1 do
  1433. begin
  1434. new(deref);
  1435. ppufile.getderef(deref^);
  1436. unitimportsymsderefs.add(deref);
  1437. end;
  1438. end;
  1439. procedure tppumodule.readasmsyms;
  1440. var
  1441. c,i : longint;
  1442. name : TSymStr;
  1443. bind : TAsmsymbind;
  1444. typ : TAsmsymtype;
  1445. list : tfphashobjectlist;
  1446. begin
  1447. case tunitasmlisttype(ppufile.getbyte) of
  1448. ualt_public:
  1449. list:=publicasmsyms;
  1450. ualt_extern:
  1451. list:=externasmsyms;
  1452. end;
  1453. c:=ppufile.getlongint;
  1454. for i:=0 to c-1 do
  1455. begin
  1456. name:=ppufile.getstring;
  1457. bind:=TAsmsymbind(ppufile.getbyte);
  1458. typ:=TAsmsymtype(ppufile.getbyte);
  1459. TAsmSymbol.Create(list,name,bind,typ);
  1460. end;
  1461. end;
  1462. procedure tppumodule.readextraheader;
  1463. begin
  1464. longversion:=cardinal(ppufile.getlongint);
  1465. ppufile.getset(tppuset4(moduleflags));
  1466. end;
  1467. procedure tppumodule.load_interface;
  1468. var
  1469. b : byte;
  1470. newmodulename : string;
  1471. begin
  1472. { read interface part }
  1473. repeat
  1474. b:=ppufile.readentry;
  1475. case b of
  1476. ibjvmnamespace :
  1477. begin
  1478. namespace:=ppufile.getpshortstring;
  1479. end;
  1480. ibmodulename :
  1481. begin
  1482. newmodulename:=ppufile.getstring;
  1483. if (cs_check_unit_name in current_settings.globalswitches) and
  1484. (upper(newmodulename)<>modulename^) then
  1485. Message2(unit_f_unit_name_error,realmodulename^,newmodulename);
  1486. stringdispose(modulename);
  1487. stringdispose(realmodulename);
  1488. modulename:=stringdup(upper(newmodulename));
  1489. realmodulename:=stringdup(newmodulename);
  1490. end;
  1491. ibextraheader:
  1492. begin
  1493. readextraheader;
  1494. end;
  1495. ibfeatures :
  1496. begin
  1497. ppufile.getset(tppuset4(features));
  1498. end;
  1499. ibmoduleoptions:
  1500. begin
  1501. ppufile.getset(tppuset1(moduleoptions));
  1502. if mo_has_deprecated_msg in moduleoptions then
  1503. begin
  1504. stringdispose(deprecatedmsg);
  1505. deprecatedmsg:=ppufile.getpshortstring;
  1506. end;
  1507. end;
  1508. ibsourcefiles :
  1509. readsourcefiles;
  1510. {$IFDEF MACRO_DIFF_HINT}
  1511. ibusedmacros :
  1512. readusedmacros;
  1513. {$ENDIF}
  1514. ibloadunit :
  1515. readloadunit;
  1516. iblinkunitofiles :
  1517. readlinkcontainer(LinkUnitOFiles);
  1518. iblinkunitstaticlibs :
  1519. readlinkcontainer(LinkUnitStaticLibs);
  1520. iblinkunitsharedlibs :
  1521. readlinkcontainer(LinkUnitSharedLibs);
  1522. iblinkotherofiles :
  1523. readlinkcontainer(LinkotherOFiles);
  1524. iblinkotherstaticlibs :
  1525. readlinkcontainer(LinkotherStaticLibs);
  1526. iblinkothersharedlibs :
  1527. readlinkcontainer(LinkotherSharedLibs);
  1528. iblinkotherframeworks :
  1529. readlinkcontainer(LinkOtherFrameworks);
  1530. ibmainname:
  1531. begin
  1532. mainname:=ppufile.getpshortstring;
  1533. if (mainaliasname<>defaultmainaliasname) then
  1534. Message1(scan_w_multiple_main_name_overrides,mainaliasname);
  1535. mainaliasname:=mainname^;
  1536. end;
  1537. ibImportSymbols :
  1538. readImportSymbols;
  1539. ibderefmap :
  1540. readderefmap;
  1541. ibderefdata :
  1542. readderefdata;
  1543. ibresources:
  1544. readResources;
  1545. iborderedsymbols:
  1546. readOrderedSymbols;
  1547. ibwpofile:
  1548. readwpofile;
  1549. ibendinterface :
  1550. break;
  1551. else
  1552. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1553. end;
  1554. { we can already stop when we know that we must recompile }
  1555. if state=ms_compile then
  1556. exit;
  1557. until false;
  1558. end;
  1559. procedure tppumodule.load_implementation;
  1560. var
  1561. b : byte;
  1562. begin
  1563. { read implementation part }
  1564. repeat
  1565. b:=ppufile.readentry;
  1566. case b of
  1567. ibloadunit :
  1568. readloadunit;
  1569. ibasmsymbols :
  1570. readasmsyms;
  1571. ibunitimportsyms:
  1572. readunitimportsyms;
  1573. ibendimplementation :
  1574. break;
  1575. else
  1576. Message1(unit_f_ppu_invalid_entry,tostr(b));
  1577. end;
  1578. until false;
  1579. end;
  1580. procedure tppumodule.writeppu;
  1581. begin
  1582. Message1(unit_u_ppu_write,realmodulename^);
  1583. { create unit flags }
  1584. {$ifdef cpufpemu}
  1585. if (cs_fp_emulation in current_settings.moduleswitches) then
  1586. headerflags:=headerflags or uf_fpu_emulation;
  1587. {$endif cpufpemu}
  1588. { create new ppufile }
  1589. ppufile:=tcompilerppufile.create(ppufilename);
  1590. if not ppufile.createfile then
  1591. Message(unit_f_ppu_cannot_write);
  1592. {$ifdef Test_Double_checksum_write}
  1593. { Re-use the values collected in .INT part }
  1594. if assigned(interface_crc_array) then
  1595. begin
  1596. ppufile.implementation_write_crc_index:=implementation_write_crc_index;
  1597. ppufile.interface_write_crc_index:=interface_write_crc_index;
  1598. ppufile.indirect_write_crc_index:=indirect_write_crc_index;
  1599. if assigned(ppufile.interface_crc_array) then
  1600. begin
  1601. dispose(ppufile.interface_crc_array);
  1602. ppufile.interface_crc_array:=interface_crc_array;
  1603. end;
  1604. if assigned(ppufile.implementation_crc_array) then
  1605. begin
  1606. dispose(ppufile.implementation_crc_array);
  1607. ppufile.implementation_crc_array:=implementation_crc_array;
  1608. end;
  1609. if assigned(ppufile.indirect_crc_array) then
  1610. begin
  1611. dispose(ppufile.indirect_crc_array);
  1612. ppufile.indirect_crc_array:=indirect_crc_array;
  1613. end;
  1614. end;
  1615. if FileExists(ppufilename+'.IMP',false) then
  1616. RenameFile(ppufilename+'.IMP',ppufilename+'.IMP-old');
  1617. Assign(ppufile.CRCFile,ppufilename+'.IMP');
  1618. Rewrite(ppufile.CRCFile);
  1619. Writeln(ppufile.CRCFile,'CRC in writeppu method of implementation of ',ppufilename,' defsgeneration=',defsgeneration);
  1620. {$endif def Test_Double_checksum_write}
  1621. { extra header (sub version, module flags) }
  1622. writeextraheader;
  1623. { first the (JVM) namespace }
  1624. if assigned(namespace) then
  1625. begin
  1626. ppufile.putstring(namespace^);
  1627. ppufile.writeentry(ibjvmnamespace);
  1628. end;
  1629. { the unitname }
  1630. ppufile.putstring(realmodulename^);
  1631. ppufile.writeentry(ibmodulename);
  1632. ppufile.putset(tppuset1(moduleoptions));
  1633. if mo_has_deprecated_msg in moduleoptions then
  1634. ppufile.putstring(deprecatedmsg^);
  1635. ppufile.writeentry(ibmoduleoptions);
  1636. { write the alternate main procedure name if any }
  1637. if assigned(mainname) then
  1638. begin
  1639. ppufile.putstring(mainname^);
  1640. ppufile.writeentry(ibmainname);
  1641. end;
  1642. if cs_compilesystem in current_settings.moduleswitches then
  1643. begin
  1644. ppufile.putset(tppuset4(features));
  1645. ppufile.writeentry(ibfeatures);
  1646. end;
  1647. writesourcefiles;
  1648. {$IFDEF MACRO_DIFF_HINT}
  1649. writeusedmacros;
  1650. {$ENDIF}
  1651. { write interface uses }
  1652. writeusedunit(true);
  1653. { write the objectfiles and libraries that come for this unit,
  1654. preserve the containers because they are still needed to load
  1655. the link.res.
  1656. All doesn't depend on the crc! It doesn't matter
  1657. if a unit is in a .o or .a file }
  1658. ppufile.do_crc:=false;
  1659. { write after source files, so that we know whether or not the compiler
  1660. will recompile the unit when checking whether the correct wpo file is
  1661. used (if it will recompile the unit anyway, it doesn't matter)
  1662. }
  1663. if (wpofeedbackinput<>'') then
  1664. begin
  1665. ppufile.putstring(wpofeedbackinput);
  1666. ppufile.putlongint(getnamedfiletime(wpofeedbackinput));
  1667. ppufile.writeentry(ibwpofile);
  1668. end;
  1669. writelinkcontainer(linkunitofiles,iblinkunitofiles,true);
  1670. writelinkcontainer(linkunitstaticlibs,iblinkunitstaticlibs,true);
  1671. writelinkcontainer(linkunitsharedlibs,iblinkunitsharedlibs,true);
  1672. writelinkcontainer(linkotherofiles,iblinkotherofiles,false);
  1673. writelinkcontainer(linkotherstaticlibs,iblinkotherstaticlibs,true);
  1674. writelinkcontainer(linkothersharedlibs,iblinkothersharedlibs,true);
  1675. writelinkcontainer(linkotherframeworks,iblinkotherframeworks,true);
  1676. writeImportSymbols;
  1677. writeResources;
  1678. writeOrderedSymbols;
  1679. ppufile.do_crc:=true;
  1680. { generate implementation deref data, the interface deref data is
  1681. already generated when calculating the interface crc }
  1682. if (cs_compilesystem in current_settings.moduleswitches) then
  1683. begin
  1684. tstoredsymtable(globalsymtable).buildderef;
  1685. derefdataintflen:=derefdata.size;
  1686. end
  1687. else
  1688. { the unit may have been re-resolved, in which case the current
  1689. position in derefdata is not necessarily at the end }
  1690. derefdata.seek(derefdata.size);
  1691. tstoredsymtable(globalsymtable).buildderefimpl;
  1692. tunitwpoinfo(wpoinfo).buildderef;
  1693. tunitwpoinfo(wpoinfo).buildderefimpl;
  1694. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1695. begin
  1696. tstoredsymtable(globalmacrosymtable).buildderef;
  1697. tstoredsymtable(globalmacrosymtable).buildderefimpl;
  1698. end;
  1699. if mf_local_symtable in moduleflags then
  1700. tstoredsymtable(localsymtable).buildderef_registered;
  1701. buildderefunitimportsyms;
  1702. writederefmap;
  1703. writederefdata;
  1704. ppufile.writeentry(ibendinterface);
  1705. { write the symtable entries }
  1706. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1707. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1708. begin
  1709. ppufile.putbyte(byte(true));
  1710. ppufile.writeentry(ibexportedmacros);
  1711. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1712. end
  1713. else
  1714. begin
  1715. ppufile.putbyte(byte(false));
  1716. ppufile.writeentry(ibexportedmacros);
  1717. end;
  1718. { everything after this doesn't affect the crc }
  1719. ppufile.do_crc:=false;
  1720. { write implementation uses }
  1721. writeusedunit(false);
  1722. { write all public assembler symbols }
  1723. writeasmsyms(ualt_public,publicasmsyms);
  1724. { write all external assembler symbols }
  1725. writeasmsyms(ualt_extern,externasmsyms);
  1726. { write all symbols imported from another unit }
  1727. writeunitimportsyms;
  1728. { end of implementation }
  1729. ppufile.writeentry(ibendimplementation);
  1730. { write static symtable
  1731. needed for local debugging of unit functions }
  1732. if mf_local_symtable in moduleflags then
  1733. tstoredsymtable(localsymtable).ppuwrite(ppufile);
  1734. { write whole program optimisation-related information }
  1735. tunitwpoinfo(wpoinfo).ppuwrite(ppufile);
  1736. { the last entry ibend is written automatically }
  1737. { flush to be sure }
  1738. ppufile.flush;
  1739. { create and write header }
  1740. ppufile.header.common.size:=ppufile.size;
  1741. ppufile.header.checksum:=ppufile.crc;
  1742. ppufile.header.interface_checksum:=interface_crc;
  1743. ppufile.header.indirect_checksum:=indirect_crc;
  1744. ppufile.header.common.compiler:=wordversion;
  1745. ppufile.header.common.cpu:=word(target_cpu);
  1746. ppufile.header.common.target:=word(target_info.system);
  1747. ppufile.header.common.flags:=headerflags;
  1748. ppufile.header.deflistsize:=current_module.deflist.count;
  1749. ppufile.header.symlistsize:=current_module.symlist.count;
  1750. ppufile.writeheader;
  1751. { save crc in current module also }
  1752. crc_final:=true;
  1753. crc:=ppufile.crc;
  1754. // make sure, the interface_crc is not affected by the implementation
  1755. // interface_crc:=ppufile.interface_crc;
  1756. // indirect_crc:=ppufile.indirect_crc;
  1757. {$IFDEF Debug_WaitCRC}
  1758. writeln('tppumodule.writeppu ',realmodulename^,' crc=',hexstr(crc,8));
  1759. {$ENDIF}
  1760. {$ifdef Test_Double_checksum_write}
  1761. Writeln(ppufile.CRCFile,'End of implementation CRC in writeppu method of ',ppufilename,
  1762. ' implementation_crc=$',hexstr(ppufile.crc,8),
  1763. ' interface_crc=$',hexstr(ppufile.interface_crc,8),
  1764. ' indirect_crc=$',hexstr(ppufile.indirect_crc,8),
  1765. ' implementation_crc_size=',ppufile.implementation_read_crc_index,
  1766. ' interface_crc_size=',ppufile.interface_read_crc_index,
  1767. ' indirect_crc_size=',ppufile.indirect_read_crc_index,
  1768. ' defsgeneration=',defsgeneration);
  1769. close(ppufile.CRCFile);
  1770. {$endif Test_Double_checksum_write}
  1771. discardppu;
  1772. end;
  1773. procedure tppumodule.getppucrc;
  1774. begin
  1775. { create new ppufile }
  1776. ppufile:=tcompilerppufile.create(ppufilename);
  1777. ppufile.crc_only:=true;
  1778. if not ppufile.createfile then
  1779. Message(unit_f_ppu_cannot_write);
  1780. {$ifdef DEBUG_GENERATE_INTERFACE_PPU}
  1781. if ppufile.writing_interface_ppu then
  1782. ppufile.crc_only:=false;
  1783. {$endif DEBUG_GENERATE_INTERFACE_PPU}
  1784. {$ifdef Test_Double_checksum_write}
  1785. if FileExists(ppufilename+'.INT',false) then
  1786. RenameFile(ppufilename+'.INT',ppufilename+'.INT-old');
  1787. Assign(ppufile.CRCFile,ppufilename+'.INT');
  1788. Rewrite(ppufile.CRCFile);
  1789. Writeln(ppufile.CRCFile,'CRC of getppucrc of ',ppufilename,
  1790. ' defsgeneration=',defsgeneration);
  1791. {$endif def Test_Double_checksum_write}
  1792. { extra header (sub version, module flags) }
  1793. writeextraheader;
  1794. { first the (JVM) namespace }
  1795. if assigned(namespace) then
  1796. begin
  1797. ppufile.putstring(namespace^);
  1798. ppufile.writeentry(ibjvmnamespace);
  1799. end;
  1800. { the unitname }
  1801. ppufile.putstring(realmodulename^);
  1802. ppufile.writeentry(ibmodulename);
  1803. ppufile.putset(tppuset1(moduleoptions));
  1804. if mo_has_deprecated_msg in moduleoptions then
  1805. ppufile.putstring(deprecatedmsg^);
  1806. ppufile.writeentry(ibmoduleoptions);
  1807. { the interface units affect the crc }
  1808. writeusedunit(true);
  1809. { deref data of interface that affect the crc }
  1810. derefdata.reset;
  1811. tstoredsymtable(globalsymtable).buildderef;
  1812. derefdataintflen:=derefdata.size;
  1813. writederefmap;
  1814. writederefdata;
  1815. ppufile.writeentry(ibendinterface);
  1816. { write the symtable entries }
  1817. tstoredsymtable(globalsymtable).ppuwrite(ppufile);
  1818. if assigned(globalmacrosymtable) and (globalmacrosymtable.SymList.count > 0) then
  1819. begin
  1820. ppufile.putbyte(byte(true));
  1821. ppufile.writeentry(ibexportedmacros);
  1822. tstoredsymtable(globalmacrosymtable).ppuwrite(ppufile);
  1823. end
  1824. else
  1825. begin
  1826. ppufile.putbyte(byte(false));
  1827. ppufile.writeentry(ibexportedmacros);
  1828. end;
  1829. { save crc }
  1830. crc:=ppufile.crc;
  1831. if in_interface then
  1832. begin
  1833. // Note: the interface_crc is not affected by the implementation
  1834. interface_crc:=ppufile.interface_crc;
  1835. indirect_crc:=ppufile.indirect_crc;
  1836. end;
  1837. {$IFDEF Debug_WaitCRC}
  1838. writeln('tppumodule.getppucrc ',realmodulename^,' in_interface=',in_interface,' crc=',hexstr(crc,8),' interface_crc=',hexstr(interface_crc,8),' indirect_crc=',hexstr(indirect_crc,8));
  1839. {$ENDIF}
  1840. { end of implementation, to generate a correct ppufile
  1841. for ppudump when using DEBUG_GENERATE_INTERFACE_PPU define }
  1842. ppufile.writeentry(ibendimplementation);
  1843. {$ifdef Test_Double_checksum_write}
  1844. Writeln(ppufile.CRCFile,'End of CRC of getppucrc of ',ppufilename,
  1845. ' implementation_crc=$',hexstr(ppufile.crc,8),
  1846. ' interface_crc=$',hexstr(ppufile.interface_crc,8),
  1847. ' indirect_crc=$',hexstr(ppufile.indirect_crc,8),
  1848. ' implementation_crc_size=',ppufile.implementation_write_crc_index,
  1849. ' interface_crc_size=',ppufile.interface_write_crc_index,
  1850. ' indirect_crc_size=',ppufile.indirect_write_crc_index,
  1851. ' defsgeneration=',defsgeneration);
  1852. close(ppufile.CRCFile);
  1853. { Remember the values generated in .INT part }
  1854. implementation_write_crc_index:=ppufile.implementation_write_crc_index;
  1855. interface_write_crc_index:=ppufile.interface_write_crc_index;
  1856. indirect_write_crc_index:=ppufile.indirect_write_crc_index;
  1857. interface_crc_array:=ppufile.interface_crc_array;
  1858. ppufile.interface_crc_array:=nil;
  1859. implementation_crc_array:=ppufile.implementation_crc_array;
  1860. ppufile.implementation_crc_array:=nil;
  1861. indirect_crc_array:=ppufile.indirect_crc_array;
  1862. ppufile.indirect_crc_array:=nil;
  1863. {$endif Test_Double_checksum_write}
  1864. { create and write header, this will only be used
  1865. for debugging purposes }
  1866. ppufile.header.common.size:=ppufile.size;
  1867. ppufile.header.checksum:=crc;
  1868. ppufile.header.interface_checksum:=interface_crc;
  1869. ppufile.header.indirect_checksum:=indirect_crc;
  1870. ppufile.header.common.compiler:=wordversion;
  1871. ppufile.header.common.cpu:=word(target_cpu);
  1872. ppufile.header.common.target:=word(target_info.system);
  1873. ppufile.header.common.flags:=headerflags;
  1874. ppufile.writeheader;
  1875. discardppu;
  1876. end;
  1877. function tppumodule.load_usedunits: boolean;
  1878. // self is a ppu (or in a package)
  1879. var
  1880. pu : tused_unit;
  1881. begin
  1882. Result:=true;
  1883. if current_module<>self then
  1884. internalerror(200212284);
  1885. if not interface_compiled then
  1886. begin
  1887. { load the used units from interface }
  1888. in_interface:=true;
  1889. {$IFDEF EnableCTaskPPU}
  1890. if not load_usedunits_section then
  1891. exit(false); // e.g. fail or some used unit interface is not ready
  1892. {$ELSE}
  1893. pu:=tused_unit(used_units.first);
  1894. while assigned(pu) do
  1895. begin
  1896. if pu.in_interface then
  1897. begin
  1898. tppumodule(pu.u).loadppu(self);
  1899. { if this unit is scheduled for compilation or compiled we can stop }
  1900. if state<>ms_load then
  1901. exit;
  1902. { add this unit to the dependencies }
  1903. pu.u.adddependency(self,true);
  1904. { need to recompile the current unit, check the interface
  1905. crc. And when not compiled with -Ur then check the complete
  1906. crc }
  1907. if (pu.u.interface_crc<>pu.interface_checksum) or
  1908. (pu.u.indirect_crc<>pu.indirect_checksum) or
  1909. (
  1910. (not(mf_release in moduleflags)) and
  1911. (pu.u.crc<>pu.checksum)
  1912. ) then
  1913. begin
  1914. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename,@queuecomment);
  1915. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1916. if (pu.u.interface_crc<>pu.interface_checksum) then
  1917. Comment(V_Normal,' intfcrc change: '+hexstr(pu.u.interface_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.interface_checksum,8)+' in unit '+realmodulename^)
  1918. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1919. Comment(V_Normal,' indcrc change: '+hexstr(pu.u.indirect_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.indirect_checksum,8)+' in unit '+realmodulename^)
  1920. else
  1921. Comment(V_Normal,' implcrc change: '+hexstr(pu.u.crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.checksum,8)+' in unit '+realmodulename^);
  1922. {$endif DEBUG_UNIT_CRC_CHANGES}
  1923. recompile_reason:=rr_crcchanged;
  1924. {$IFDEF DEBUG_PPU_CYCLES}
  1925. writeln('PPUALGO tppumodule.load_usedunits ',modulename^,' interface uses "',pu.u.modulename^,'" old=',state,' new=',ms_compile);
  1926. {$ENDIF}
  1927. state:=ms_compile;
  1928. exit;
  1929. end;
  1930. end;
  1931. pu:=tused_unit(pu.next);
  1932. end;
  1933. {$ENDIF}
  1934. { ok, now load the interface of this unit }
  1935. if current_module<>self then
  1936. internalerror(200208187);
  1937. deflist.count:=ppufile.header.deflistsize;
  1938. symlist.count:=ppufile.header.symlistsize;
  1939. globalsymtable:=tglobalsymtable.create(realmodulename^,moduleid);
  1940. tstoredsymtable(globalsymtable).ppuload(ppufile);
  1941. if ppufile.readentry<>ibexportedmacros then
  1942. Message(unit_f_ppu_read_error);
  1943. if boolean(ppufile.getbyte) then
  1944. begin
  1945. globalmacrosymtable:=tmacrosymtable.Create(true);
  1946. tstoredsymtable(globalmacrosymtable).ppuload(ppufile)
  1947. end;
  1948. interface_compiled:=true;
  1949. { read the implementation part, containing
  1950. the implementation uses and ObjData }
  1951. in_interface:=false;
  1952. load_implementation;
  1953. end;
  1954. { now only read the implementation uses }
  1955. {$IFDEF EnableCTaskPPU}
  1956. if not ppu_waitingfor_crc then
  1957. begin
  1958. if not load_usedunits_section then
  1959. exit(false); // fail or some used unit interface is not ready
  1960. end;
  1961. {$ELSE}
  1962. pu:=tused_unit(used_units.first);
  1963. while assigned(pu) do
  1964. begin
  1965. if (not pu.in_interface) then
  1966. begin
  1967. tppumodule(pu.u).loadppu(self);
  1968. { if this unit is compiled we can stop }
  1969. if state=ms_compiled then
  1970. exit;
  1971. { add this unit to the dependencies }
  1972. pu.u.adddependency(self,false);
  1973. { need to recompile the current unit ? }
  1974. if (pu.u.interface_crc<>pu.interface_checksum) or
  1975. (pu.u.indirect_crc<>pu.indirect_checksum) then
  1976. begin
  1977. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename+' {impl}',@queuecomment);
  1978. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  1979. if (pu.u.interface_crc<>pu.interface_checksum) then
  1980. Comment(V_Normal,' intfcrc change (2): '+hexstr(pu.u.interface_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.interface_checksum,8)+' in unit '+realmodulename^)
  1981. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  1982. Comment(V_Normal,' indcrc change (2): '+hexstr(pu.u.indirect_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.indirect_checksum,8)+' in unit '+realmodulename^);
  1983. {$endif DEBUG_UNIT_CRC_CHANGES}
  1984. recompile_reason:=rr_crcchanged;
  1985. {$IFDEF DEBUG_PPU_CYCLES}
  1986. writeln('PPUALGO tppumodule.load_usedunits ',modulename^,' implementation uses "',pu.u.modulename^,'" old=',state,' new=',ms_compile);
  1987. {$ENDIF}
  1988. state:=ms_compile;
  1989. exit;
  1990. end;
  1991. end;
  1992. pu:=tused_unit(pu.next);
  1993. end;
  1994. {$ENDIF}
  1995. {$IFDEF EnableCTaskPPU}
  1996. if not ppu_waitingfor_crc then
  1997. {$ENDIF}
  1998. begin
  1999. { load implementation symtable }
  2000. if mf_local_symtable in moduleflags then
  2001. begin
  2002. localsymtable:=tstaticsymtable.create(realmodulename^,moduleid);
  2003. tstaticsymtable(localsymtable).ppuload(ppufile);
  2004. end;
  2005. { we can now dereference all pointers to the implementation parts }
  2006. tstoredsymtable(globalsymtable).derefimpl(false);
  2007. { we've just loaded the localsymtable from the ppu file, so everything
  2008. in it was registered by definition (otherwise it wouldn't have been in
  2009. there) }
  2010. if assigned(localsymtable) then
  2011. tstoredsymtable(localsymtable).derefimpl(false);
  2012. derefunitimportsyms;
  2013. { read whole program optimisation-related information }
  2014. wpoinfo:=tunitwpoinfo.ppuload(ppufile);
  2015. tunitwpoinfo(wpoinfo).deref;
  2016. tunitwpoinfo(wpoinfo).derefimpl;
  2017. end;
  2018. {$IFDEF EnableCTaskPPU}
  2019. // check CRCs
  2020. ppu_waitingfor_crc:=true;
  2021. if not ppu_check_used_crcs then exit;
  2022. state:=ms_compiled;
  2023. {$ENDIF}
  2024. end;
  2025. {$IFDEF EnableCTaskPPU}
  2026. function tppumodule.load_usedunits_section: boolean;
  2027. var
  2028. pu: tused_unit;
  2029. IntfCRCValid, CRCValid: Boolean;
  2030. begin
  2031. Result:=true;
  2032. pu:=tused_unit(used_units.first);
  2033. while assigned(pu) do
  2034. begin
  2035. if pu.in_interface=in_interface then
  2036. begin
  2037. tppumodule(pu.u).loadppu(self);
  2038. { if this unit is scheduled for compilation or compiled we can stop }
  2039. if state<>ms_load then
  2040. begin
  2041. {$IFDEF DEBUG_PPU_CYCLES}
  2042. writeln('tppumodule.load_usedunits_section STOPPED ',modulename^,' ',statestr);
  2043. {$ENDIF}
  2044. exit(false);
  2045. end;
  2046. {$IFDEF DEBUG_PPU_CYCLES}
  2047. writeln('PPUALGO tppumodule.load_usedunits_section ',modulename^,' (',statestr,') ',BoolToStr(in_interface,'interface','implementation'),' uses "',pu.u.modulename^,'" state=',pu.u.statestr);
  2048. {$ENDIF}
  2049. if not pu.dependent_added then
  2050. begin
  2051. { add this unit to the dependencies }
  2052. pu.u.adddependency(self,true);
  2053. pu.dependent_added:=true;
  2054. end;
  2055. { check crc(s) if recompile is needed.
  2056. Currently ppus wait for a pas to be compiled, because a ppu cannot
  2057. use only the interface of a pas.
  2058. If an unit of a cycle is recompiled, the whole cycle is recompiled.
  2059. If this ppu was compiled with -Ur only check interface_crc, not crc }
  2060. CRCValid:=(not pu.u.do_reload) and (pu.u.state in [ms_load,ms_compiled_waitcrc,ms_compiled,ms_processed]);
  2061. IntfCRCValid:=CRCValid {or (pu.u.state in [ms_compiling_waitimpl,ms_compiling_waitfinish,ms_compiled_waitcrc])};
  2062. if (IntfCRCValid and
  2063. ((pu.u.interface_crc<>pu.interface_checksum) or
  2064. (pu.u.indirect_crc<>pu.indirect_checksum)))
  2065. or (CRCValid and
  2066. (not (mf_release in moduleflags)) and
  2067. (pu.u.crc<>pu.checksum)
  2068. ) then
  2069. begin
  2070. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename,@queuecomment);
  2071. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  2072. if (pu.u.interface_crc<>pu.interface_checksum) then
  2073. Comment(V_Normal,' intfcrc change: '+hexstr(pu.u.interface_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.interface_checksum,8)+' in unit '+realmodulename^)
  2074. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  2075. Comment(V_Normal,' indcrc change: '+hexstr(pu.u.indirect_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.indirect_checksum,8)+' in unit '+realmodulename^)
  2076. else
  2077. Comment(V_Normal,' implcrc change: '+hexstr(pu.u.crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.checksum,8)+' in unit '+realmodulename^);
  2078. {$endif DEBUG_UNIT_CRC_CHANGES}
  2079. recompile_reason:=rr_crcchanged;
  2080. {$IFDEF DEBUG_PPU_CYCLES}
  2081. writeln('PPUALGO tppumodule.load_usedunits_section ',modulename^,' ',BoolToStr(in_interface,'interface','implementation'),' uses "',pu.u.modulename^,'" old=',statestr,' new=',ms_compile);
  2082. {$ENDIF}
  2083. state:=ms_compile;
  2084. exit(false);
  2085. end;
  2086. if (not CRCValid) or (not pu.u.interface_compiled) then
  2087. begin
  2088. // an used unit is delayed
  2089. // Important: load the rest of the uses section
  2090. {$IFDEF DEBUG_PPU_CYCLES}
  2091. if not Result then writeln('PPUALGO tppumodule.load_usedunits_section ',modulename^,' ',BoolToStr(in_interface,'interface','implementation'),' uses "',pu.u.modulename^,'", state=',pu.u.statestr,', waiting for crc...');
  2092. {$ENDIF}
  2093. Result:=false;
  2094. end;
  2095. end;
  2096. pu:=tused_unit(pu.next);
  2097. end;
  2098. end;
  2099. function tppumodule.ppu_check_used_crcs: boolean;
  2100. var
  2101. pu: tused_unit;
  2102. begin
  2103. Result:=false;
  2104. pu:=tused_unit(used_units.first);
  2105. while assigned(pu) do
  2106. begin
  2107. if pu.u.state in [ms_load,ms_compiled_waitcrc,ms_compiled,ms_processed] then
  2108. begin
  2109. if (pu.u.crc<>pu.checksum) then
  2110. begin
  2111. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  2112. Comment(V_Normal,' implcrc change: '+hexstr(pu.u.crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.checksum,8)+' in unit '+realmodulename^);
  2113. {$endif DEBUG_UNIT_CRC_CHANGES}
  2114. recompile_reason:=rr_crcchanged;
  2115. {$IFDEF DEBUG_PPU_CYCLES}
  2116. writeln('PPUALGO tppumodule.ppu_check_used_crcs ',modulename^,' interface uses "',pu.u.modulename^,'" old=',statestr,' new=',ms_compile);
  2117. {$ENDIF}
  2118. state:=ms_compile;
  2119. exit;
  2120. end;
  2121. end else begin
  2122. // waiting for crc
  2123. exit;
  2124. end;
  2125. pu:=tused_unit(pu.next);
  2126. end;
  2127. Result:=true;
  2128. end;
  2129. function tppumodule.ppuloadcancontinue(out firstwaiting: tmodule): boolean;
  2130. var
  2131. pu: tused_unit;
  2132. uses_busy, check: Boolean;
  2133. begin
  2134. Result:=false;
  2135. firstwaiting:=nil;
  2136. if state<>ms_load then
  2137. Internalerror(2026020610);
  2138. if do_reload and not interface_compiled then
  2139. exit(true);
  2140. pu:=tused_unit(used_units.first);
  2141. while assigned(pu) do
  2142. begin
  2143. check:=false;
  2144. if do_reload then
  2145. // waiting for referenced used units
  2146. check:=pu.in_interface or ppu_waitingfor_crc
  2147. else if not interface_compiled then
  2148. // waiting for interface uses
  2149. check:=pu.in_interface
  2150. else if not ppu_waitingfor_crc then
  2151. // waiting for implementation uses
  2152. check:=not pu.in_interface
  2153. else
  2154. // waiting for crcs
  2155. check:=true;
  2156. if check then
  2157. begin
  2158. if not (pu.u.state in [ms_load,ms_compiled_waitcrc,ms_compiled,ms_processed])
  2159. or not pu.u.interface_compiled
  2160. or pu.u.do_reload
  2161. then
  2162. begin
  2163. firstwaiting:=pu.u;
  2164. exit;
  2165. end;
  2166. end;
  2167. pu:=tused_unit(pu.next);
  2168. end;
  2169. Result:=true;
  2170. end;
  2171. function tppumodule.is_reload_needed(pu: tdependent_unit): boolean;
  2172. begin
  2173. if pu.u.state=ms_load then
  2174. Result:=tppumodule(pu.u).ppu_waitingfor_crc
  2175. or (pu.in_interface and pu.u.interface_compiled)
  2176. else
  2177. Result:=inherited is_reload_needed(pu);
  2178. end;
  2179. procedure tppumodule.recompile_cycle;
  2180. var
  2181. from_module: tmodule;
  2182. begin
  2183. recompile_reason:=rr_buildcycle;
  2184. from_module:=current_module;
  2185. set_current_module(self);
  2186. recompile_from_sources(loadedfrommodule);
  2187. set_current_module(from_module);
  2188. end;
  2189. {$ENDIF EnableCTaskPPU}
  2190. function tppumodule.needrecompile:boolean;
  2191. var
  2192. pu : tused_unit;
  2193. begin
  2194. result:=false;
  2195. pu:=tused_unit(used_units.first);
  2196. while assigned(pu) do
  2197. begin
  2198. { need to recompile the current unit, check the interface
  2199. crc. And when not compiled with -Ur then check the complete
  2200. crc }
  2201. if (pu.u.interface_crc<>pu.interface_checksum) or
  2202. (pu.u.indirect_crc<>pu.indirect_checksum) or
  2203. (
  2204. (pu.in_interface) and
  2205. (pu.u.crc<>pu.checksum)
  2206. ) then
  2207. begin
  2208. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  2209. if (pu.u.interface_crc<>pu.interface_checksum) then
  2210. Comment(V_Normal,' intfcrc change (3): '+hexstr(pu.u.interface_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.interface_checksum,8)+' in unit '+realmodulename^)
  2211. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  2212. Comment(V_Normal,' indcrc change (3): '+hexstr(pu.u.indirect_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.indirect_checksum,8)+' in unit '+realmodulename^)
  2213. else
  2214. Comment(V_Normal,' implcrc change (3): '+hexstr(pu.u.crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.checksum,8)+' in unit '+realmodulename^);
  2215. {$endif DEBUG_UNIT_CRC_CHANGES}
  2216. result:=true;
  2217. exit;
  2218. end;
  2219. pu:=tused_unit(pu.next);
  2220. end;
  2221. end;
  2222. procedure tppumodule.setdefgeneration;
  2223. begin
  2224. defsgeneration:=currentdefgeneration;
  2225. inc(currentdefgeneration);
  2226. end;
  2227. procedure tppumodule.reload_flagged_units;
  2228. var
  2229. hp : tppumodule;
  2230. begin
  2231. { now reload all dependent units with outdated defs }
  2232. hp:=tppumodule(loaded_units.first);
  2233. while assigned(hp) do
  2234. begin
  2235. if hp.do_reload and
  2236. (hp.defsgeneration<defsgeneration) then
  2237. begin
  2238. hp.defsgeneration:=defsgeneration;
  2239. hp.loadppu(self);
  2240. end
  2241. else
  2242. hp.do_reload:=false;
  2243. hp:=tppumodule(hp.next);
  2244. end;
  2245. end;
  2246. procedure tppumodule.end_of_parsing;
  2247. begin
  2248. { module is now compiled }
  2249. state:=ms_compiled;
  2250. { free ppu }
  2251. discardppu;
  2252. inherited end_of_parsing;
  2253. end;
  2254. procedure tppumodule.check_reload(from_module : tmodule; var do_load : boolean);
  2255. begin
  2256. { A force reload }
  2257. if not do_reload then
  2258. exit;
  2259. Message(unit_u_forced_reload);
  2260. do_reload:=false;
  2261. { When the unit is already loaded or being loaded
  2262. we can maybe skip a complete reload/recompile }
  2263. if assigned(globalsymtable)
  2264. {$IFDEF EnableCTaskPPU}
  2265. {$ELSE}
  2266. and (not needrecompile)
  2267. {$ENDIF}
  2268. then
  2269. begin
  2270. { When we don't have any data stored yet there
  2271. is nothing to resolve }
  2272. if interface_compiled and
  2273. { it makes no sense to re-resolve the unit if it is already finally compiled }
  2274. not (state in [ms_compiled,ms_processed]) then
  2275. begin
  2276. re_resolve(from_module);
  2277. end
  2278. else
  2279. Message1(unit_u_skipping_reresolving_unit,modulename^);
  2280. do_load:=false;
  2281. end;
  2282. end;
  2283. { Returns true if the module was loaded from package }
  2284. function tppumodule.check_loadfrompackage : boolean;
  2285. begin
  2286. { try to load it as a package unit first }
  2287. Result:=(packagelist.count>0) and loadfrompackage;
  2288. if Result then
  2289. begin
  2290. do_reload:=false;
  2291. state:=ms_compiled;
  2292. { PPU is not needed anymore }
  2293. if assigned(ppufile) then
  2294. begin
  2295. discardppu;
  2296. end;
  2297. { add the unit to the used units list of the program }
  2298. usedunits.concat(tused_unit.create(self,true,false,nil));
  2299. end;
  2300. end;
  2301. procedure tppumodule.prepare_second_load(from_module: tmodule);
  2302. const
  2303. CompileStates = [ms_compile, ms_compiling_wait,
  2304. ms_compiling_waitintf, ms_compiling_waitimpl, ms_compiling_waitfinish,
  2305. ms_compiled_waitcrc, ms_compiled, ms_processed];
  2306. begin
  2307. { try to load the unit a second time first }
  2308. Message1(unit_u_second_load_unit,modulename^);
  2309. Message2(unit_u_previous_state,modulename^,ModuleStateStr[state]);
  2310. { Flag modules to reload }
  2311. flagdependent(from_module);
  2312. { Reset the module }
  2313. reset(false);
  2314. if state in CompileStates then
  2315. begin
  2316. Message1(unit_u_second_compile_unit,modulename^);
  2317. {$IFDEF DEBUG_PPU_CYCLES}
  2318. writeln('PPUALGO tppumodule.prepare_second_load ',modulename^,' old=',state,' new=',ms_compile);
  2319. {$ENDIF}
  2320. state:=ms_compile;
  2321. end
  2322. else
  2323. state:=ms_load;
  2324. end;
  2325. procedure tppumodule.try_load_ppufile(from_module : tmodule);
  2326. begin
  2327. Message1(unit_u_loading_unit,modulename^);
  2328. if auPPU in search_unit_files(from_module,false) then
  2329. state:=ms_load
  2330. else begin
  2331. {$IFDEF DEBUG_PPU_CYCLES}
  2332. writeln('PPUALGO tppumodule.try_load_ppufile ',modulename^,' no ppu found old=',state,' new=',ms_compile);
  2333. {$ENDIF}
  2334. state:=ms_compile;
  2335. end;
  2336. if state=ms_load then
  2337. begin
  2338. load_interface;
  2339. setdefgeneration;
  2340. if state=ms_load then
  2341. begin
  2342. load_usedunits;
  2343. if state=ms_load then begin
  2344. {$IFDEF DEBUG_PPU_CYCLES}
  2345. writeln('PPUALGO tppumodule.try_load_ppufile ',modulename^,' state=',state,' do_reload=',do_reload);
  2346. {$ENDIF}
  2347. Message1(unit_u_finished_loading_unit,modulename^);
  2348. end;
  2349. end;
  2350. end;
  2351. { PPU is not needed anymore }
  2352. if assigned(ppufile) then
  2353. discardppu;
  2354. end;
  2355. procedure tppumodule.recompile_from_sources(from_module : tmodule);
  2356. var
  2357. pu : tused_unit;
  2358. was_interfaced_compiled: Boolean;
  2359. begin
  2360. { recompile the unit or give a fatal error if sources not available }
  2361. if not sources_avail then
  2362. begin
  2363. search_unit_files(from_module,true);
  2364. if not sources_avail then
  2365. begin
  2366. printcomments;
  2367. if recompile_reason=rr_noppu then
  2368. begin
  2369. pu:=tused_unit(from_module.used_units.first);
  2370. while assigned(pu) do
  2371. begin
  2372. if pu.u=self then
  2373. break;
  2374. pu:=tused_unit(pu.next);
  2375. end;
  2376. if assigned(pu) and assigned(pu.unitsym) then
  2377. MessagePos2(pu.unitsym.fileinfo,unit_f_cant_find_ppu,realmodulename^,from_module.realmodulename^)
  2378. else
  2379. Message2(unit_f_cant_find_ppu,realmodulename^,from_module.realmodulename^);
  2380. end
  2381. else
  2382. Message1(unit_f_cant_compile_unit,realmodulename^);
  2383. end;
  2384. end;
  2385. { we found the sources, we do not need the verbose messages anymore }
  2386. if comments <> nil then
  2387. begin
  2388. comments.free;
  2389. comments:=nil;
  2390. end;
  2391. {$IFDEF DEBUG_PPU_CYCLES}
  2392. writeln('PPUALGO tppumodule.recompile_from_sources ',modulename^,' old=',statestr,' new=',ms_compile);
  2393. {$ENDIF}
  2394. { Flag modules to reload }
  2395. flagdependent(from_module);
  2396. {$IFDEF EnableCTaskPPU}
  2397. was_interfaced_compiled:=interface_compiled;
  2398. { disconnect dependending modules }
  2399. disconnect_depending_modules;
  2400. {$ENDIF}
  2401. { Reset the module }
  2402. reset(true);
  2403. { mark this module for recompilation }
  2404. state:=ms_compile;
  2405. {$IFDEF EnableCTaskPPU}
  2406. if was_interfaced_compiled then
  2407. setdefgeneration;
  2408. queue_module(Self); // queue after reset, so task state is cleared!
  2409. {$ELSE}
  2410. setdefgeneration;
  2411. {$ENDIF}
  2412. end;
  2413. procedure tppumodule.post_load_or_compile(from_module : tmodule; second_time : boolean);
  2414. begin
  2415. if current_module<>self then
  2416. internalerror(200212282);
  2417. if in_interface then
  2418. internalerror(200212283);
  2419. {$IFDEF EnableCTaskPPU}
  2420. {$ELSE}
  2421. { for a second_time recompile reload all dependent units,
  2422. for a first time compile register the unit _once_ }
  2423. if second_time or do_reload then
  2424. reload_flagged_units;
  2425. {$ENDIF}
  2426. { reopen the old module }
  2427. {$ifdef SHORT_ON_FILE_HANDLES}
  2428. if from_module.is_unit and
  2429. assigned(tppumodule(from_module).ppufile) then
  2430. tppumodule(from_module).ppufile.tempopen;
  2431. {$endif SHORT_ON_FILE_HANDLES}
  2432. state:=ms_processed;
  2433. end;
  2434. function tppumodule.loadppu(from_module : tmodule) : boolean;
  2435. const
  2436. ImplIntf : array[boolean] of string[15]=('implementation','interface');
  2437. {$IFDEF EnableCTaskPPU}
  2438. begin
  2439. Result:=false;
  2440. writeln('PPUALGO tppumodule.loadppu START ',modulename^,' (',statestr,') used by "',from_module.modulename^,'" (',from_module.statestr,')');
  2441. Message3(unit_u_load_unit,from_module.modulename^,
  2442. ImplIntf[from_module.in_interface],
  2443. modulename^);
  2444. if do_reload then
  2445. exit(false); // delay reload until used units are ready
  2446. if state>ms_registered then
  2447. exit(interface_compiled);
  2448. loadedfrommodule:=from_module;
  2449. set_current_module(self);
  2450. if check_loadfrompackage then
  2451. begin
  2452. // No need to do anything, restore situation and exit.
  2453. set_current_module(from_module);
  2454. {$IFDEF DEBUG_PPU_CYCLES}
  2455. writeln('PPUALGO tppumodule.loadppu from package: ',modulename^,' (',statestr,') used by "',from_module.modulename^,'" (',from_module.statestr,')');
  2456. {$ENDIF}
  2457. exit(state in [ms_compiled,ms_processed]);
  2458. end;
  2459. { close old_current_ppu on system that are
  2460. short on file handles like DOS PM }
  2461. {$ifdef SHORT_ON_FILE_HANDLES}
  2462. if from_module.is_unit and
  2463. assigned(tppumodule(from_module).ppufile) then
  2464. tppumodule(from_module).ppufile.tempclose;
  2465. {$endif SHORT_ON_FILE_HANDLES}
  2466. // search ppu file
  2467. Message1(unit_u_loading_unit,modulename^);
  2468. if auPPU in search_unit_files(from_module,false) then
  2469. begin
  2470. state:=ms_load;
  2471. fromppu:=true;
  2472. load_interface;
  2473. end
  2474. else begin
  2475. {$IFDEF DEBUG_PPU_CYCLES}
  2476. writeln('PPUALGO tppumodule.try_load_ppufile ',modulename^,' no ppu found old=',statestr,' new=',ms_compile);
  2477. {$ENDIF}
  2478. // recompile_reason is already set by search_unit_files
  2479. state:=ms_compile;
  2480. end;
  2481. Result:=continueloadppu;
  2482. set_current_module(from_module);
  2483. end;
  2484. {$ELSE}
  2485. var
  2486. do_load,
  2487. second_time: boolean;
  2488. begin
  2489. Result:=false;
  2490. Inc(LoadCount);
  2491. Message3(unit_u_load_unit,from_module.modulename^,
  2492. ImplIntf[from_module.in_interface],
  2493. modulename^);
  2494. { check if the globalsymtable is already available, but
  2495. we must reload when the do_reload flag is set
  2496. The globalsymtable is created after loading the interface ppus }
  2497. if (not do_reload) and
  2498. assigned(globalsymtable) then
  2499. exit(True);
  2500. { reset }
  2501. do_load:=true;
  2502. second_time:=false;
  2503. set_current_module(self);
  2504. do_load:=not check_loadfrompackage;
  2505. { A force reload }
  2506. check_reload(from_module, do_load);
  2507. if not do_load then
  2508. begin
  2509. // No need to do anything, restore situation and exit.
  2510. set_current_module(from_module);
  2511. exit(state=ms_compiled);
  2512. end;
  2513. { loading the unit for a second time? }
  2514. {$IFDEF DEBUG_PPU_CYCLES}
  2515. writeln('PPUALGO tppumodule.loadppu ',modulename^,' ',state);
  2516. {$ENDIF}
  2517. if state=ms_registered then
  2518. state:=ms_load
  2519. else if (state in [ms_compile, ms_compiling_waitintf]) then
  2520. begin
  2521. { no use continuing if we must be compiled }
  2522. // but we still need to restore current_module!
  2523. set_current_module(from_module);
  2524. exit(false);
  2525. end
  2526. else
  2527. begin
  2528. { ppu cycle, e.g. A intf uses B impl uses A }
  2529. second_time:=true;
  2530. prepare_second_load(from_module);
  2531. {$IFDEF DEBUG_PPU_CYCLES}
  2532. writeln('PPUALGO tppumodule.loadppu AFTER prepare_second_load ',modulename^,' ',state);
  2533. {$ENDIF}
  2534. end;
  2535. { close old_current_ppu on system that are
  2536. short on file handles like DOS PM }
  2537. {$ifdef SHORT_ON_FILE_HANDLES}
  2538. if from_module.is_unit and
  2539. assigned(tppumodule(from_module).ppufile) then
  2540. tppumodule(from_module).ppufile.tempclose;
  2541. {$endif SHORT_ON_FILE_HANDLES}
  2542. { try opening ppu, skip this when we already
  2543. know that we need to compile the unit }
  2544. if not (state=ms_compile) then
  2545. try_load_ppufile(from_module);
  2546. { Do we need to recompile the unit }
  2547. if (state=ms_compile) then
  2548. recompile_from_sources(from_module)
  2549. else
  2550. state:=ms_compiled;
  2551. Result:=(state=ms_compiled);
  2552. // We cannot do this here, the order is all messed up...
  2553. // if not second_time then
  2554. // usedunits.concat(tused_unit.create(self,true,false,nil));
  2555. if result then
  2556. post_load_or_compile(from_module,second_time);
  2557. { we are back, restore current_module }
  2558. set_current_module(from_module);
  2559. { safety, so it does not become negative }
  2560. if LoadCount>0 then
  2561. Dec(LoadCount);
  2562. end;
  2563. {$ENDIF}
  2564. {$ifdef EnableCTaskPPU}
  2565. function tppumodule.continueloadppu: boolean;
  2566. var
  2567. old_module: tmodule;
  2568. do_load: boolean;
  2569. pu: tused_unit;
  2570. begin
  2571. old_module:=current_module;
  2572. set_current_module(self);
  2573. if do_reload then
  2574. Internalerror(2026021017);
  2575. if state=ms_load then
  2576. begin
  2577. if load_usedunits then
  2578. begin
  2579. {$IFDEF DEBUG_PPU_CYCLES}
  2580. writeln('PPUALGO tppumodule.continueloadppu ',modulename^,' finished state=',statestr);
  2581. {$ENDIF}
  2582. Message1(unit_u_finished_loading_unit,modulename^);
  2583. end else if state=ms_load then
  2584. begin
  2585. {$IFDEF DEBUG_PPU_CYCLES}
  2586. writeln('PPUALGO tppumodule.continueloadppu ',modulename^,' delay state=',statestr);
  2587. {$ENDIF}
  2588. { loading unfinished or reset, restore current_module }
  2589. set_current_module(old_module);
  2590. queue_module(Self);
  2591. exit;
  2592. end else if state<>ms_compile then
  2593. internalerror(2026020510);
  2594. end;
  2595. { PPU is not needed anymore }
  2596. if assigned(ppufile) then
  2597. discardppu;
  2598. if state=ms_compiled then
  2599. begin
  2600. Result:=true;
  2601. post_load_or_compile(loadedfrommodule,false);
  2602. end else if state=ms_compile then
  2603. recompile_from_sources(loadedfrommodule)
  2604. else begin
  2605. queue_module(Self);
  2606. end;
  2607. { we are back, restore current_module }
  2608. set_current_module(old_module);
  2609. end;
  2610. function tppumodule.canreload(out firstwaiting: tmodule): boolean;
  2611. var
  2612. check_impl_uses, check_crc: Boolean;
  2613. pu: tused_unit;
  2614. begin
  2615. firstwaiting:=nil;
  2616. if not interface_compiled then
  2617. exit(true);
  2618. // if implementation was parsed then implementation uses must be checked too
  2619. if state=ms_load then
  2620. check_impl_uses:=ppu_waitingfor_crc
  2621. else
  2622. check_impl_uses:=state in [ms_compiling_waitimpl..ms_compiled,ms_processed];
  2623. // if the crc(s) of used unit are known
  2624. check_crc:=state in [ms_load,ms_compiled,ms_processed];
  2625. pu:=tused_unit(used_units.first);
  2626. while assigned(pu) do
  2627. begin
  2628. if pu.in_interface or check_impl_uses then
  2629. begin
  2630. if not pu.u.interface_compiled
  2631. or pu.u.do_reload
  2632. or (check_crc
  2633. and not (pu.u.state in [ms_load,ms_compiled_waitcrc,ms_compiled,ms_processed])) then
  2634. begin
  2635. firstwaiting:=pu.u;
  2636. exit(false);
  2637. end;
  2638. end;
  2639. pu:=tused_unit(pu.next);
  2640. end;
  2641. Result:=true;
  2642. end;
  2643. procedure tppumodule.reload;
  2644. var
  2645. pu: tused_unit;
  2646. do_load, check_impl_uses, check_crc: Boolean;
  2647. begin
  2648. if not do_reload then
  2649. Internalerror(2026021015);
  2650. if fromppu and (state in [ms_compiled,ms_processed]) then
  2651. begin
  2652. // reload ppu: check crcs again
  2653. state:=ms_load;
  2654. ppu_waitingfor_crc:=true;
  2655. end;
  2656. if interface_compiled then
  2657. begin
  2658. // if implementation was parsed then implementation uses must be checked too
  2659. if state=ms_load then
  2660. check_impl_uses:=ppu_waitingfor_crc
  2661. else
  2662. check_impl_uses:=state in [ms_compiling_waitimpl..ms_compiled,ms_processed];
  2663. // if the crc(s) of used unit are known
  2664. check_crc:=state in [ms_load,ms_compiled,ms_processed];
  2665. pu:=tused_unit(used_units.first);
  2666. while assigned(pu) do
  2667. begin
  2668. if pu.in_interface or check_impl_uses then
  2669. begin
  2670. if not pu.u.interface_compiled
  2671. or pu.u.do_reload
  2672. or (check_crc
  2673. and not (pu.u.state in [ms_load,ms_compiled_waitcrc,ms_compiled,ms_processed])) then
  2674. begin
  2675. // bug in ctask.cancontinue
  2676. writeln('tppumodule.continueloadppu reloading ',modulename^,', but ',pu.u.modulename^,' not ready (',pu.u.statestr,').');
  2677. Internalerror(2026020918);
  2678. end;
  2679. if (pu.u.interface_crc<>pu.interface_checksum) or
  2680. (pu.u.indirect_crc<>pu.indirect_checksum)
  2681. or (check_crc and
  2682. (not (mf_release in moduleflags)) and
  2683. (pu.u.crc<>pu.checksum)
  2684. ) then
  2685. begin
  2686. Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.ppufilename,@queuecomment);
  2687. {$ifdef DEBUG_UNIT_CRC_CHANGES}
  2688. if (pu.u.interface_crc<>pu.interface_checksum) then
  2689. Comment(V_Normal,' intfcrc change: '+hexstr(pu.u.interface_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.interface_checksum,8)+' in unit '+realmodulename^)
  2690. else if (pu.u.indirect_crc<>pu.indirect_checksum) then
  2691. Comment(V_Normal,' indcrc change: '+hexstr(pu.u.indirect_crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.indirect_checksum,8)+' in unit '+realmodulename^)
  2692. else
  2693. Comment(V_Normal,' implcrc change: '+hexstr(pu.u.crc,8)+' for '+pu.u.ppufilename+' <> '+hexstr(pu.checksum,8)+' in unit '+realmodulename^);
  2694. {$endif DEBUG_UNIT_CRC_CHANGES}
  2695. recompile_reason:=rr_crcchanged;
  2696. {$IFDEF DEBUG_PPU_CYCLES}
  2697. writeln('PPUALGO tppumodule.reload ',modulename^,' ',BoolToStr(in_interface,'interface','implementation'),' uses "',pu.u.modulename^,'" old=',statestr,' new=',ms_compile);
  2698. {$ENDIF}
  2699. state:=ms_compile;
  2700. exit;
  2701. end;
  2702. end;
  2703. pu:=tused_unit(pu.next);
  2704. end;
  2705. end;
  2706. do_load:=true;
  2707. check_reload(loadedfrommodule,do_load);
  2708. end;
  2709. {$endif}
  2710. procedure tppumodule.discardppu;
  2711. begin
  2712. { PPU is not needed anymore }
  2713. if not assigned(ppufile) then
  2714. exit;
  2715. ppufile.closefile;
  2716. ppufile.free;
  2717. ppufile:=nil;
  2718. end;
  2719. {*****************************************************************************
  2720. RegisterUnit
  2721. *****************************************************************************}
  2722. function registerunit(callermodule:tmodule;const s : TIDString;const fn:string; out is_new:boolean) : tppumodule;
  2723. function FindCycle(aFile, SearchFor: TModule; var Cycle: TFPList): boolean;
  2724. // Note: when traversing, add every search file to Cycle, to avoid running in circles.
  2725. // When a cycle is detected, clear the Cycle list and build the cycle path
  2726. var
  2727. aParent: tdependent_unit;
  2728. begin
  2729. Cycle.Add(aFile);
  2730. aParent:=tdependent_unit(afile.dependent_units.First);
  2731. While Assigned(aParent) do
  2732. begin
  2733. if aParent.in_interface then
  2734. begin
  2735. // writeln('Registering ',Callermodule.get_modulename,': checking cyclic dependency of ',aFile.get_modulename, ' on ',aparent.u.get_modulename);
  2736. if aParent.u=SearchFor then
  2737. begin
  2738. // unit cycle found
  2739. Cycle.Clear;
  2740. Cycle.Add(aParent.u);
  2741. Cycle.Add(aFile);
  2742. // Writeln('exit at ',aParent.u.get_modulename);
  2743. exit(true);
  2744. end;
  2745. if Cycle.IndexOf(aParent.u)<0 then
  2746. if FindCycle(aParent.u,SearchFor,Cycle) then
  2747. begin
  2748. // Writeln('Cycle found, exit at ',aParent.u.get_modulename);
  2749. Cycle.Add(aFile);
  2750. exit(true);
  2751. end;
  2752. end;
  2753. aParent:=tdependent_unit(aParent.Next);
  2754. end;
  2755. Result:=false;
  2756. end;
  2757. var
  2758. ups : TIDString;
  2759. hp : tppumodule;
  2760. hp2 : tmodule;
  2761. cycle : TFPList;
  2762. havecycle: boolean;
  2763. {$IFDEF DEBUGCYCLE}
  2764. cyclepath : ansistring
  2765. {$ENDIF}
  2766. begin
  2767. { Info }
  2768. ups:=upper(s);
  2769. { search all loaded units }
  2770. hp:=tppumodule(loaded_units.first);
  2771. hp2:=nil;
  2772. while assigned(hp) do
  2773. begin
  2774. if hp.modulename^=ups then
  2775. begin
  2776. { only check for units. The main program is also
  2777. as a unit in the loaded_units list. We simply need
  2778. to ignore this entry (PFV) }
  2779. if hp.is_unit then
  2780. begin
  2781. { both units in interface ? }
  2782. if hp.in_interface and callermodule.in_interface then
  2783. begin
  2784. { check for a cycle }
  2785. Cycle:=TFPList.Create;
  2786. try
  2787. HaveCycle:=FindCycle(CallerModule,hp,Cycle);
  2788. if HaveCycle then
  2789. begin
  2790. {$IFDEF DEBUGCYCLE}
  2791. Writeln('Done cycle check');
  2792. CyclePath:='';
  2793. hp2:=TModule(Cycle[Cycle.Count-1]);
  2794. for i:=0 to Cycle.Count-1 do begin
  2795. if i>0 then CyclePath:=CyclePath+',';
  2796. CyclePath:=CyclePath+TModule(Cycle[i]).realmodulename^;
  2797. end;
  2798. Writeln('Unit cycle detected: ',CyclePath);
  2799. {$ENDIF}
  2800. Message2(unit_f_circular_unit_reference,callermodule.realmodulename^,hp.realmodulename^);
  2801. end;
  2802. finally
  2803. Cycle.Free;
  2804. Cycle := nil;
  2805. end;
  2806. if assigned(hp2) then
  2807. Message2(unit_f_circular_unit_reference,callermodule.realmodulename^,hp.realmodulename^);
  2808. end;
  2809. break;
  2810. end;
  2811. end;
  2812. { the next unit }
  2813. hp:=tppumodule(hp.next);
  2814. end;
  2815. { the unit is not in the loaded units,
  2816. we create an entry and register the unit }
  2817. is_new:=not assigned(hp);
  2818. if is_new then
  2819. begin
  2820. Message1(unit_u_registering_new_unit,ups);
  2821. hp:=tppumodule.create(callermodule,s,fn,true);
  2822. addloadedunit(hp);
  2823. end;
  2824. { return }
  2825. registerunit:=hp;
  2826. end;
  2827. end.