2
0

pmodules.pas 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288
  1. {
  2. Copyright (c) 1998-2008 by Florian Klaempfl
  3. Handles the parsing and loading of the modules (ppufiles)
  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 pmodules;
  18. {$i fpcdefs.inc}
  19. interface
  20. procedure proc_unit;
  21. procedure proc_package;
  22. procedure proc_program(islibrary : boolean);
  23. implementation
  24. uses
  25. SysUtils,
  26. globtype,version,systems,tokens,
  27. cutils,cfileutl,cclasses,comphook,
  28. globals,verbose,fmodule,finput,fppu,
  29. symconst,symbase,symtype,symdef,symsym,symtable,
  30. wpoinfo,
  31. aasmtai,aasmdata,aasmcpu,aasmbase,
  32. cgbase,cgobj,
  33. nbas,ncgutil,
  34. link,assemble,import,export,gendef,ppu,comprsrc,dbgbase,
  35. cresstr,procinfo,
  36. pexports,
  37. wpobase,
  38. scanner,pbase,pexpr,psystem,psub,pdecsub,ptype
  39. ,cpuinfo
  40. {$ifdef i386}
  41. { fix me! }
  42. ,cpubase
  43. {$endif i386}
  44. ;
  45. procedure create_objectfile;
  46. var
  47. DLLScanner : TDLLScanner;
  48. s : string;
  49. KeepShared : TCmdStrList;
  50. begin
  51. { try to create import entries from system dlls }
  52. if (tf_has_dllscanner in target_info.flags) and
  53. (not current_module.linkOtherSharedLibs.Empty) then
  54. begin
  55. { Init DLLScanner }
  56. if assigned(CDLLScanner[target_info.system]) then
  57. DLLScanner:=CDLLScanner[target_info.system].Create
  58. else
  59. internalerror(200104121);
  60. KeepShared:=TCmdStrList.Create;
  61. { Walk all shared libs }
  62. While not current_module.linkOtherSharedLibs.Empty do
  63. begin
  64. S:=current_module.linkOtherSharedLibs.Getusemask(link_always);
  65. if not DLLScanner.scan(s) then
  66. KeepShared.Concat(s);
  67. end;
  68. DLLscanner.Free;
  69. { Recreate import section }
  70. if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
  71. begin
  72. if assigned(current_asmdata.asmlists[al_imports]) then
  73. current_asmdata.asmlists[al_imports].clear
  74. else
  75. current_asmdata.asmlists[al_imports]:=TAsmList.Create;
  76. importlib.generatelib;
  77. end;
  78. { Readd the not processed files }
  79. while not KeepShared.Empty do
  80. begin
  81. s:=KeepShared.GetFirst;
  82. current_module.linkOtherSharedLibs.add(s,link_always);
  83. end;
  84. KeepShared.Free;
  85. end;
  86. { Start and end module debuginfo, at least required for stabs
  87. to insert n_sourcefile lines }
  88. if (cs_debuginfo in current_settings.moduleswitches) or
  89. (cs_use_lineinfo in current_settings.globalswitches) then
  90. current_debuginfo.insertmoduleinfo;
  91. { create the .s file and assemble it }
  92. GenerateAsm(false);
  93. { Also create a smartlinked version ? }
  94. if create_smartlink_library then
  95. begin
  96. GenerateAsm(true);
  97. if (af_needar in target_asm.flags) then
  98. Linker.MakeStaticLibrary;
  99. end;
  100. { resource files }
  101. CompileResourceFiles;
  102. end;
  103. procedure insertobjectfile;
  104. { Insert the used object file for this unit in the used list for this unit }
  105. begin
  106. current_module.linkunitofiles.add(current_module.objfilename^,link_static);
  107. current_module.flags:=current_module.flags or uf_static_linked;
  108. if create_smartlink_library then
  109. begin
  110. current_module.linkunitstaticlibs.add(current_module.staticlibfilename^,link_smart);
  111. current_module.flags:=current_module.flags or uf_smart_linked;
  112. end;
  113. end;
  114. procedure create_dwarf_frame;
  115. begin
  116. { Dwarf conflicts with smartlinking in separate .a files }
  117. if create_smartlink_library then
  118. exit;
  119. { Call frame information }
  120. { MWE: we write our own info, so dwarf asm support is not really needed }
  121. { if (af_supports_dwarf in target_asm.flags) and }
  122. { CFI is currently broken for Darwin }
  123. if not(target_info.system in systems_darwin) and
  124. (
  125. (tf_needs_dwarf_cfi in target_info.flags) or
  126. (paratargetdbg in [dbg_dwarf2, dbg_dwarf3])
  127. ) then
  128. begin
  129. current_asmdata.asmlists[al_dwarf_frame].Free;
  130. current_asmdata.asmlists[al_dwarf_frame] := TAsmList.create;
  131. current_asmdata.asmcfi.generate_code(current_asmdata.asmlists[al_dwarf_frame]);
  132. end;
  133. end;
  134. procedure InsertThreadvarTablesTable;
  135. var
  136. hp : tused_unit;
  137. ltvTables : TAsmList;
  138. count : longint;
  139. begin
  140. if (tf_section_threadvars in target_info.flags) then
  141. exit;
  142. ltvTables:=TAsmList.Create;
  143. count:=0;
  144. hp:=tused_unit(usedunits.first);
  145. while assigned(hp) do
  146. begin
  147. If (hp.u.flags and uf_threadvars)=uf_threadvars then
  148. begin
  149. ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',hp.u.globalsymtable,''),0));
  150. inc(count);
  151. end;
  152. hp:=tused_unit(hp.next);
  153. end;
  154. { Add program threadvars, if any }
  155. If (current_module.flags and uf_threadvars)=uf_threadvars then
  156. begin
  157. ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',current_module.localsymtable,''),0));
  158. inc(count);
  159. end;
  160. { Insert TableCount at start }
  161. ltvTables.insert(Tai_const.Create_32bit(count));
  162. { insert in data segment }
  163. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  164. new_section(current_asmdata.asmlists[al_globals],sec_data,'FPC_THREADVARTABLES',sizeof(pint));
  165. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('FPC_THREADVARTABLES',AT_DATA,0));
  166. current_asmdata.asmlists[al_globals].concatlist(ltvTables);
  167. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('FPC_THREADVARTABLES'));
  168. ltvTables.free;
  169. end;
  170. procedure AddToThreadvarList(p:TObject;arg:pointer);
  171. var
  172. ltvTable : TAsmList;
  173. begin
  174. ltvTable:=TAsmList(arg);
  175. if (tsym(p).typ=staticvarsym) and
  176. (vo_is_thread_var in tstaticvarsym(p).varoptions) then
  177. begin
  178. { address of threadvar }
  179. ltvTable.concat(tai_const.Createname(tstaticvarsym(p).mangledname,0));
  180. { size of threadvar }
  181. ltvTable.concat(tai_const.create_32bit(tstaticvarsym(p).getsize));
  182. end;
  183. end;
  184. procedure InsertThreadvars;
  185. var
  186. s : string;
  187. ltvTable : TAsmList;
  188. begin
  189. if (tf_section_threadvars in target_info.flags) then
  190. exit;
  191. ltvTable:=TAsmList.create;
  192. if assigned(current_module.globalsymtable) then
  193. current_module.globalsymtable.SymList.ForEachCall(@AddToThreadvarList,ltvTable);
  194. current_module.localsymtable.SymList.ForEachCall(@AddToThreadvarList,ltvTable);
  195. if ltvTable.first<>nil then
  196. begin
  197. s:=make_mangledname('THREADVARLIST',current_module.localsymtable,'');
  198. { end of the list marker }
  199. ltvTable.concat(tai_const.create_sym(nil));
  200. { add to datasegment }
  201. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  202. new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
  203. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  204. current_asmdata.asmlists[al_globals].concatlist(ltvTable);
  205. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
  206. current_module.flags:=current_module.flags or uf_threadvars;
  207. end;
  208. ltvTable.Free;
  209. end;
  210. procedure MaybeGenerateObjectiveCImageInfo;
  211. begin
  212. if (m_objectivec1 in current_settings.modeswitches) then
  213. begin
  214. { first 4 bytes contain version information about this section (currently version 0),
  215. next 4 bytes contain flags (currently only regarding whether the code in the object
  216. file supports or requires garbage collection)
  217. }
  218. new_section(current_asmdata.asmlists[al_objc_data],sec_objc_image_info,'_OBJC_IMAGE_INFO',4);
  219. current_asmdata.asmlists[al_objc_data].concat(Tai_symbol.Createname(target_asm.labelprefix+'_OBJC_IMAGE_INFO',AT_LABEL,8));
  220. current_asmdata.asmlists[al_objc_data].concat(Tai_const.Create_64bit(0));
  221. end;
  222. end;
  223. Function CheckResourcesUsed : boolean;
  224. var
  225. hp : tused_unit;
  226. found : Boolean;
  227. begin
  228. CheckResourcesUsed:=tf_has_winlike_resources in target_info.flags;
  229. if not CheckResourcesUsed then exit;
  230. hp:=tused_unit(usedunits.first);
  231. found:=((current_module.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
  232. If not found then
  233. While Assigned(hp) and not found do
  234. begin
  235. Found:=((hp.u.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
  236. hp:=tused_unit(hp.next);
  237. end;
  238. CheckResourcesUsed:=found;
  239. end;
  240. Procedure InsertResourceInfo(ResourcesUsed : boolean);
  241. var
  242. ResourceInfo : TAsmList;
  243. begin
  244. if (target_res.id in [res_elf,res_macho]) then
  245. begin
  246. ResourceInfo:=TAsmList.Create;
  247. maybe_new_object_file(ResourceInfo);
  248. new_section(ResourceInfo,sec_data,'FPC_RESLOCATION',sizeof(aint));
  249. ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESLOCATION',AT_DATA,0));
  250. if ResourcesUsed then
  251. { Valid pointer to resource information }
  252. ResourceInfo.concat(Tai_const.Createname('FPC_RESSYMBOL',0))
  253. else
  254. { Nil pointer to resource information }
  255. {$IFDEF CPU32}
  256. ResourceInfo.Concat(Tai_const.Create_32bit(0));
  257. {$ELSE}
  258. ResourceInfo.Concat(Tai_const.Create_64bit(0));
  259. {$ENDIF}
  260. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  261. current_asmdata.asmlists[al_globals].concatlist(ResourceInfo);
  262. ResourceInfo.free;
  263. end;
  264. end;
  265. Procedure InsertResourceTablesTable;
  266. var
  267. hp : tmodule;
  268. ResourceStringTables : tasmlist;
  269. count : longint;
  270. begin
  271. ResourceStringTables:=tasmlist.Create;
  272. count:=0;
  273. hp:=tmodule(loaded_units.first);
  274. while assigned(hp) do
  275. begin
  276. If (hp.flags and uf_has_resourcestrings)=uf_has_resourcestrings then
  277. begin
  278. ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESSTR',hp.localsymtable,'START'),0));
  279. ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESSTR',hp.localsymtable,'END'),0));
  280. inc(count);
  281. end;
  282. hp:=tmodule(hp.next);
  283. end;
  284. { Insert TableCount at start }
  285. ResourceStringTables.insert(Tai_const.Create_pint(count));
  286. { Add to data segment }
  287. maybe_new_object_file(current_asmdata.AsmLists[al_globals]);
  288. new_section(current_asmdata.AsmLists[al_globals],sec_data,'FPC_RESOURCESTRINGTABLES',sizeof(pint));
  289. current_asmdata.AsmLists[al_globals].concat(Tai_symbol.Createname_global('FPC_RESOURCESTRINGTABLES',AT_DATA,0));
  290. current_asmdata.AsmLists[al_globals].concatlist(ResourceStringTables);
  291. current_asmdata.AsmLists[al_globals].concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
  292. ResourceStringTables.free;
  293. end;
  294. procedure InsertInitFinalTable;
  295. var
  296. hp : tused_unit;
  297. unitinits : TAsmList;
  298. count : longint;
  299. begin
  300. unitinits:=TAsmList.Create;
  301. count:=0;
  302. hp:=tused_unit(usedunits.first);
  303. while assigned(hp) do
  304. begin
  305. { call the unit init code and make it external }
  306. if (hp.u.flags and (uf_init or uf_finalize))<>0 then
  307. begin
  308. if (hp.u.flags and uf_init)<>0 then
  309. unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',hp.u.globalsymtable,''),0))
  310. else
  311. unitinits.concat(Tai_const.Create_sym(nil));
  312. if (hp.u.flags and uf_finalize)<>0 then
  313. unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',hp.u.globalsymtable,''),0))
  314. else
  315. unitinits.concat(Tai_const.Create_sym(nil));
  316. inc(count);
  317. end;
  318. hp:=tused_unit(hp.next);
  319. end;
  320. { Insert initialization/finalization of the program }
  321. if (current_module.flags and (uf_init or uf_finalize))<>0 then
  322. begin
  323. if (current_module.flags and uf_init)<>0 then
  324. unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',current_module.localsymtable,''),0))
  325. else
  326. unitinits.concat(Tai_const.Create_sym(nil));
  327. if (current_module.flags and uf_finalize)<>0 then
  328. unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',current_module.localsymtable,''),0))
  329. else
  330. unitinits.concat(Tai_const.Create_sym(nil));
  331. inc(count);
  332. end;
  333. { Insert TableCount,InitCount at start }
  334. unitinits.insert(Tai_const.Create_32bit(0));
  335. unitinits.insert(Tai_const.Create_32bit(count));
  336. { Add to data segment }
  337. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  338. new_section(current_asmdata.asmlists[al_globals],sec_data,'INITFINAL',sizeof(pint));
  339. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('INITFINAL',AT_DATA,0));
  340. current_asmdata.asmlists[al_globals].concatlist(unitinits);
  341. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('INITFINAL'));
  342. unitinits.free;
  343. end;
  344. procedure insertmemorysizes;
  345. {$IFDEF POWERPC}
  346. var
  347. stkcookie: string;
  348. {$ENDIF POWERPC}
  349. begin
  350. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  351. { Insert Ident of the compiler in the .fpc.version section }
  352. current_asmdata.asmlists[al_globals].concat(Tai_section.create(sec_fpc,'version',0));
  353. current_asmdata.asmlists[al_globals].concat(Tai_align.Create(const_align(32)));
  354. current_asmdata.asmlists[al_globals].concat(Tai_string.Create('FPC '+full_version_string+
  355. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname));
  356. if not(tf_no_generic_stackcheck in target_info.flags) then
  357. begin
  358. { stacksize can be specified and is now simulated }
  359. new_section(current_asmdata.asmlists[al_globals],sec_data,'__stklen', sizeof(pint));
  360. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__stklen',AT_DATA,sizeof(pint)));
  361. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(stacksize));
  362. end;
  363. {$IFDEF POWERPC}
  364. { AmigaOS4 "stack cookie" support }
  365. if ( target_info.system = system_powerpc_amiga ) then
  366. begin
  367. { this symbol is needed to ignite powerpc amigaos' }
  368. { stack allocation magic for us with the given stack size. }
  369. { note: won't work for m68k amigaos or morphos. (KB) }
  370. str(stacksize,stkcookie);
  371. stkcookie:='$STACK: '+stkcookie+#0;
  372. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  373. new_section(current_asmdata.asmlists[al_globals],sec_data,'__stack_cookie',length(stkcookie));
  374. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__stack_cookie',AT_DATA,length(stkcookie)));
  375. current_asmdata.asmlists[al_globals].concat(Tai_string.Create(stkcookie));
  376. end;
  377. {$ENDIF POWERPC}
  378. { Initial heapsize }
  379. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  380. new_section(current_asmdata.asmlists[al_globals],sec_data,'__heapsize',sizeof(pint));
  381. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__heapsize',AT_DATA,sizeof(pint)));
  382. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(heapsize));
  383. { Initial heapsize }
  384. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  385. new_section(current_asmdata.asmlists[al_globals],sec_data,'__fpc_valgrind',sizeof(boolean));
  386. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__fpc_valgrind',AT_DATA,sizeof(boolean)));
  387. current_asmdata.asmlists[al_globals].concat(Tai_const.create_8bit(byte(cs_gdb_valgrind in current_settings.globalswitches)));
  388. end;
  389. procedure AddUnit(const s:string);
  390. var
  391. hp : tppumodule;
  392. unitsym : tunitsym;
  393. begin
  394. { load unit }
  395. hp:=registerunit(current_module,s,'');
  396. hp.loadppu;
  397. hp.adddependency(current_module);
  398. { add to symtable stack }
  399. symtablestack.push(hp.globalsymtable);
  400. if (m_mac in current_settings.modeswitches) and
  401. assigned(hp.globalmacrosymtable) then
  402. macrosymtablestack.push(hp.globalmacrosymtable);
  403. { insert unitsym }
  404. unitsym:=tunitsym.create(s,hp);
  405. inc(unitsym.refs);
  406. current_module.localsymtable.insert(unitsym);
  407. { add to used units }
  408. current_module.addusedunit(hp,false,unitsym);
  409. end;
  410. procedure maybeloadvariantsunit;
  411. var
  412. hp : tmodule;
  413. begin
  414. { Do we need the variants unit? Skip this
  415. for VarUtils unit for bootstrapping }
  416. if (current_module.flags and uf_uses_variants=0) or
  417. (current_module.modulename^='VARUTILS') then
  418. exit;
  419. { Variants unit already loaded? }
  420. hp:=tmodule(loaded_units.first);
  421. while assigned(hp) do
  422. begin
  423. if hp.modulename^='VARIANTS' then
  424. exit;
  425. hp:=tmodule(hp.next);
  426. end;
  427. { Variants unit is not loaded yet, load it now }
  428. Message(parser_w_implicit_uses_of_variants_unit);
  429. AddUnit('variants');
  430. end;
  431. function MaybeRemoveResUnit : boolean;
  432. var
  433. resources_used : boolean;
  434. hp : tmodule;
  435. uu : tused_unit;
  436. unitname : shortstring;
  437. begin
  438. { We simply remove the unit from:
  439. - usedunit list, so that things like init/finalization table won't
  440. contain references to this unit
  441. - loaded_units list, so that the unit object file doesn't get linked
  442. with the executable. }
  443. { Note: on windows we always need resources! }
  444. resources_used:=(target_info.system in system_all_windows)
  445. or CheckResourcesUsed;
  446. if (not resources_used) and (tf_has_winlike_resources in target_info.flags) then
  447. begin
  448. { resources aren't used, so we don't need this unit }
  449. if target_res.id=res_ext then
  450. unitname:='FPEXTRES'
  451. else
  452. unitname:='FPINTRES';
  453. Message1(unit_u_unload_resunit,unitname);
  454. { find the module }
  455. hp:=tmodule(loaded_units.first);
  456. while assigned(hp) do
  457. begin
  458. if hp.is_unit and (hp.modulename^=unitname) then break;
  459. hp:=tmodule(hp.next);
  460. end;
  461. if not assigned(hp) then
  462. internalerror(200801071);
  463. { find its tused_unit in the global list }
  464. uu:=tused_unit(usedunits.first);
  465. while assigned(uu) do
  466. begin
  467. if uu.u=hp then break;
  468. uu:=tused_unit(uu.next);
  469. end;
  470. if not assigned(uu) then
  471. internalerror(200801072);
  472. { remove the tused_unit }
  473. usedunits.Remove(uu);
  474. uu.Free;
  475. { remove the module }
  476. loaded_units.Remove(hp);
  477. unloaded_units.Concat(hp);
  478. end;
  479. MaybeRemoveResUnit:=resources_used;
  480. end;
  481. procedure loaddefaultunits;
  482. begin
  483. { we are going to rebuild the symtablestack, clear it first }
  484. symtablestack.clear;
  485. macrosymtablestack.clear;
  486. { macro symtable }
  487. macrosymtablestack.push(initialmacrosymtable);
  488. { are we compiling the system unit? }
  489. if (cs_compilesystem in current_settings.moduleswitches) then
  490. begin
  491. systemunit:=tglobalsymtable(current_module.localsymtable);
  492. { create system defines }
  493. create_intern_symbols;
  494. create_intern_types;
  495. { Set the owner of errorsym and errortype to symtable to
  496. prevent crashes when accessing .owner }
  497. generrorsym.owner:=systemunit;
  498. generrordef.owner:=systemunit;
  499. exit;
  500. end;
  501. { insert the system unit, it is allways the first. Load also the
  502. internal types from the system unit }
  503. AddUnit('system');
  504. systemunit:=tglobalsymtable(symtablestack.top);
  505. load_intern_types;
  506. { Set the owner of errorsym and errortype to symtable to
  507. prevent crashes when accessing .owner }
  508. generrorsym.owner:=systemunit;
  509. generrordef.owner:=systemunit;
  510. { Units only required for main module }
  511. if not(current_module.is_unit) then
  512. begin
  513. { Heaptrc unit, load heaptrace before any other units especially objpas }
  514. if (cs_use_heaptrc in current_settings.globalswitches) then
  515. AddUnit('heaptrc');
  516. { Lineinfo unit }
  517. if (cs_use_lineinfo in current_settings.globalswitches) then begin
  518. if (paratargetdbg = dbg_stabs) then
  519. AddUnit('lineinfo')
  520. else
  521. AddUnit('lnfodwrf');
  522. end;
  523. { Valgrind requires c memory manager }
  524. if (cs_gdb_valgrind in current_settings.globalswitches) then
  525. AddUnit('cmem');
  526. {$ifdef cpufpemu}
  527. { Floating point emulation unit?
  528. softfpu must be in the system unit anyways (FK)
  529. if (cs_fp_emulation in current_settings.moduleswitches) and not(target_info.system in system_wince) then
  530. AddUnit('softfpu');
  531. }
  532. {$endif cpufpemu}
  533. { Which kind of resource support?
  534. Note: if resources aren't used this unit will be removed later,
  535. otherwise we need it here since it must be loaded quite early }
  536. if (tf_has_winlike_resources in target_info.flags) then
  537. if target_res.id=res_ext then
  538. AddUnit('fpextres')
  539. else
  540. AddUnit('fpintres');
  541. end;
  542. { Objpas unit? }
  543. if m_objpas in current_settings.modeswitches then
  544. AddUnit('objpas');
  545. { Macpas unit? }
  546. if m_mac in current_settings.modeswitches then
  547. AddUnit('macpas');
  548. { Objective-C 1.0 support unit? }
  549. if (m_objectivec1 in current_settings.modeswitches) then
  550. AddUnit('objc1');
  551. { Profile unit? Needed for go32v2 only }
  552. if (cs_profile in current_settings.moduleswitches) and
  553. (target_info.system in [system_i386_go32v2,system_i386_watcom]) then
  554. AddUnit('profile');
  555. if (cs_load_fpcylix_unit in current_settings.globalswitches) then
  556. begin
  557. AddUnit('fpcylix');
  558. AddUnit('dynlibs');
  559. end;
  560. { CPU targets with microcontroller support can add a controller specific unit }
  561. {$if defined(ARM)}
  562. if (target_info.system in system_embedded) and (current_settings.controllertype<>ct_none) then
  563. AddUnit(controllerunitstr[current_settings.controllertype]);
  564. {$endif ARM}
  565. end;
  566. procedure loadautounits;
  567. var
  568. hs,s : string;
  569. begin
  570. hs:=autoloadunits;
  571. repeat
  572. s:=GetToken(hs,',');
  573. if s='' then
  574. break;
  575. AddUnit(s);
  576. until false;
  577. end;
  578. procedure loadunits;
  579. var
  580. s,sorg : TIDString;
  581. fn : string;
  582. pu : tused_unit;
  583. hp2 : tmodule;
  584. unitsym : tunitsym;
  585. begin
  586. consume(_USES);
  587. repeat
  588. s:=pattern;
  589. sorg:=orgpattern;
  590. consume(_ID);
  591. { support "<unit> in '<file>'" construct, but not for tp7 }
  592. fn:='';
  593. if not(m_tp7 in current_settings.modeswitches) and
  594. try_to_consume(_OP_IN) then
  595. fn:=FixFileName(get_stringconst);
  596. { Give a warning if lineinfo is loaded }
  597. if s='LINEINFO' then begin
  598. Message(parser_w_no_lineinfo_use_switch);
  599. if (paratargetdbg in [dbg_dwarf2, dbg_dwarf3]) then
  600. s := 'LNFODWRF';
  601. sorg := s;
  602. end;
  603. { Give a warning if objpas is loaded }
  604. if s='OBJPAS' then
  605. Message(parser_w_no_objpas_use_mode);
  606. { Using the unit itself is not possible }
  607. if (s<>current_module.modulename^) then
  608. begin
  609. { check if the unit is already used }
  610. hp2:=nil;
  611. pu:=tused_unit(current_module.used_units.first);
  612. while assigned(pu) do
  613. begin
  614. if (pu.u.modulename^=s) then
  615. begin
  616. hp2:=pu.u;
  617. break;
  618. end;
  619. pu:=tused_unit(pu.next);
  620. end;
  621. if not assigned(hp2) then
  622. hp2:=registerunit(current_module,sorg,fn)
  623. else
  624. Message1(sym_e_duplicate_id,s);
  625. { Create unitsym, we need to use the name as specified, we
  626. can not use the modulename because that can be different
  627. when -Un is used }
  628. unitsym:=tunitsym.create(sorg,nil);
  629. current_module.localsymtable.insert(unitsym);
  630. { the current module uses the unit hp2 }
  631. current_module.addusedunit(hp2,true,unitsym);
  632. end
  633. else
  634. Message1(sym_e_duplicate_id,s);
  635. if token=_COMMA then
  636. begin
  637. pattern:='';
  638. consume(_COMMA);
  639. end
  640. else
  641. break;
  642. until false;
  643. { Load the units }
  644. pu:=tused_unit(current_module.used_units.first);
  645. while assigned(pu) do
  646. begin
  647. { Only load the units that are in the current
  648. (interface/implementation) uses clause }
  649. if pu.in_uses and
  650. (pu.in_interface=current_module.in_interface) then
  651. begin
  652. tppumodule(pu.u).loadppu;
  653. { is our module compiled? then we can stop }
  654. if current_module.state=ms_compiled then
  655. exit;
  656. { add this unit to the dependencies }
  657. pu.u.adddependency(current_module);
  658. { save crc values }
  659. pu.checksum:=pu.u.crc;
  660. pu.interface_checksum:=pu.u.interface_crc;
  661. { connect unitsym to the module }
  662. pu.unitsym.module:=pu.u;
  663. { add to symtable stack }
  664. symtablestack.push(pu.u.globalsymtable);
  665. if (m_mac in current_settings.modeswitches) and
  666. assigned(pu.u.globalmacrosymtable) then
  667. macrosymtablestack.push(pu.u.globalmacrosymtable);
  668. end;
  669. pu:=tused_unit(pu.next);
  670. end;
  671. consume(_SEMICOLON);
  672. end;
  673. procedure reset_all_defs;
  674. procedure reset_used_unit_defs(hp:tmodule);
  675. var
  676. pu : tused_unit;
  677. begin
  678. pu:=tused_unit(hp.used_units.first);
  679. while assigned(pu) do
  680. begin
  681. if not pu.u.is_reset then
  682. begin
  683. { prevent infinte loop for circular dependencies }
  684. pu.u.is_reset:=true;
  685. if assigned(pu.u.globalsymtable) then
  686. begin
  687. tglobalsymtable(pu.u.globalsymtable).reset_all_defs;
  688. reset_used_unit_defs(pu.u);
  689. end;
  690. end;
  691. pu:=tused_unit(pu.next);
  692. end;
  693. end;
  694. var
  695. hp2 : tmodule;
  696. begin
  697. hp2:=tmodule(loaded_units.first);
  698. while assigned(hp2) do
  699. begin
  700. hp2.is_reset:=false;
  701. hp2:=tmodule(hp2.next);
  702. end;
  703. reset_used_unit_defs(current_module);
  704. end;
  705. procedure free_localsymtables(st:TSymtable);
  706. var
  707. i : longint;
  708. def : tstoreddef;
  709. pd : tprocdef;
  710. begin
  711. for i:=0 to st.DefList.Count-1 do
  712. begin
  713. def:=tstoreddef(st.DefList[i]);
  714. if def.typ=procdef then
  715. begin
  716. pd:=tprocdef(def);
  717. if assigned(pd.localst) and
  718. (pd.localst.symtabletype<>staticsymtable) and
  719. not(po_inline in pd.procoptions) then
  720. begin
  721. free_localsymtables(pd.localst);
  722. pd.localst.free;
  723. pd.localst:=nil;
  724. end;
  725. end;
  726. end;
  727. end;
  728. procedure parse_implementation_uses;
  729. begin
  730. if token=_USES then
  731. loadunits;
  732. end;
  733. procedure setupglobalswitches;
  734. begin
  735. if (cs_create_pic in current_settings.moduleswitches) then
  736. begin
  737. def_system_macro('FPC_PIC');
  738. def_system_macro('PIC');
  739. end;
  740. end;
  741. function create_main_proc(const name:string;potype:tproctypeoption;st:TSymtable):tcgprocinfo;
  742. var
  743. ps : tprocsym;
  744. pd : tprocdef;
  745. begin
  746. { there should be no current_procinfo available }
  747. if assigned(current_procinfo) then
  748. internalerror(200304275);
  749. {Generate a procsym for main}
  750. ps:=tprocsym.create('$'+name);
  751. { main are allways used }
  752. inc(ps.refs);
  753. st.insert(ps);
  754. pd:=tprocdef.create(main_program_level);
  755. include(pd.procoptions,po_global);
  756. pd.procsym:=ps;
  757. ps.ProcdefList.Add(pd);
  758. { set procdef options }
  759. pd.proctypeoption:=potype;
  760. pd.proccalloption:=pocall_default;
  761. include(pd.procoptions,po_hascallingconvention);
  762. pd.forwarddef:=false;
  763. pd.setmangledname(target_info.cprefix+name);
  764. pd.aliasnames.insert(pd.mangledname);
  765. handle_calling_convention(pd);
  766. { We don't need is a local symtable. Change it into the static
  767. symtable }
  768. pd.localst.free;
  769. pd.localst:=st;
  770. { set procinfo and current_procinfo.procdef }
  771. result:=tcgprocinfo(cprocinfo.create(nil));
  772. result.procdef:=pd;
  773. { main proc does always a call e.g. to init system unit }
  774. include(result.flags,pi_do_call);
  775. end;
  776. procedure release_main_proc(pi:tcgprocinfo);
  777. begin
  778. { remove localst as it was replaced by staticsymtable }
  779. pi.procdef.localst:=nil;
  780. { remove procinfo }
  781. current_module.procinfo:=nil;
  782. pi.free;
  783. pi:=nil;
  784. end;
  785. function gen_implicit_initfinal(flag:word;st:TSymtable):tcgprocinfo;
  786. begin
  787. { update module flags }
  788. current_module.flags:=current_module.flags or flag;
  789. { create procdef }
  790. case flag of
  791. uf_init :
  792. begin
  793. result:=create_main_proc(make_mangledname('',current_module.localsymtable,'init_implicit'),potype_unitinit,st);
  794. result.procdef.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
  795. end;
  796. uf_finalize :
  797. begin
  798. result:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize_implicit'),potype_unitfinalize,st);
  799. result.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
  800. if (not current_module.is_unit) then
  801. result.procdef.aliasnames.insert('PASCALFINALIZE');
  802. end;
  803. else
  804. internalerror(200304253);
  805. end;
  806. result.code:=cnothingnode.create;
  807. end;
  808. procedure copy_macro(p:TObject; arg:pointer);
  809. begin
  810. current_module.globalmacrosymtable.insert(tmacro(p).getcopy);
  811. end;
  812. procedure proc_unit;
  813. function is_assembler_generated:boolean;
  814. var
  815. hal : tasmlisttype;
  816. begin
  817. result:=false;
  818. if Errorcount=0 then
  819. begin
  820. for hal:=low(TasmlistType) to high(TasmlistType) do
  821. if not current_asmdata.asmlists[hal].empty then
  822. begin
  823. result:=true;
  824. exit;
  825. end;
  826. end;
  827. end;
  828. var
  829. main_file: tinputfile;
  830. {$ifdef EXTDEBUG}
  831. store_crc,
  832. {$endif EXTDEBUG}
  833. store_interface_crc : cardinal;
  834. s1,s2 : ^string; {Saves stack space}
  835. force_init_final : boolean;
  836. init_procinfo,
  837. finalize_procinfo : tcgprocinfo;
  838. unitname8 : string[8];
  839. ag: boolean;
  840. {$ifdef i386}
  841. gotvarsym : tstaticvarsym;
  842. {$endif i386}
  843. {$ifdef debug_devirt}
  844. i: longint;
  845. {$endif debug_devirt}
  846. begin
  847. init_procinfo:=nil;
  848. finalize_procinfo:=nil;
  849. if m_mac in current_settings.modeswitches then
  850. current_module.mode_switch_allowed:= false;
  851. consume(_UNIT);
  852. if compile_level=1 then
  853. Status.IsExe:=false;
  854. if token=_ID then
  855. begin
  856. { create filenames and unit name }
  857. main_file := current_scanner.inputfile;
  858. while assigned(main_file.next) do
  859. main_file := main_file.next;
  860. new(s1);
  861. s1^:=current_module.modulename^;
  862. current_module.SetFileName(main_file.path^+main_file.name^,true);
  863. current_module.SetModuleName(orgpattern);
  864. { check for system unit }
  865. new(s2);
  866. s2^:=upper(ChangeFileExt(ExtractFileName(main_file.name^),''));
  867. unitname8:=copy(current_module.modulename^,1,8);
  868. if (cs_check_unit_name in current_settings.globalswitches) and
  869. (
  870. not(
  871. (current_module.modulename^=s2^) or
  872. (
  873. (length(current_module.modulename^)>8) and
  874. (unitname8=s2^)
  875. )
  876. )
  877. or
  878. (
  879. (length(s1^)>8) and
  880. (s1^<>current_module.modulename^)
  881. )
  882. ) then
  883. Message1(unit_e_illegal_unit_name,current_module.realmodulename^);
  884. if (current_module.modulename^='SYSTEM') then
  885. include(current_settings.moduleswitches,cs_compilesystem);
  886. dispose(s2);
  887. dispose(s1);
  888. end;
  889. if (target_info.system in system_unit_program_exports) then
  890. exportlib.preparelib(current_module.realmodulename^);
  891. consume(_ID);
  892. consume(_SEMICOLON);
  893. consume(_INTERFACE);
  894. { global switches are read, so further changes aren't allowed }
  895. current_module.in_global:=false;
  896. { handle the global switches }
  897. setupglobalswitches;
  898. message1(unit_u_loading_interface_units,current_module.modulename^);
  899. { update status }
  900. status.currentmodule:=current_module.realmodulename^;
  901. { maybe turn off m_objpas if we are compiling objpas }
  902. if (current_module.modulename^='OBJPAS') then
  903. exclude(current_settings.modeswitches,m_objpas);
  904. { maybe turn off m_mac if we are compiling macpas }
  905. if (current_module.modulename^='MACPAS') then
  906. exclude(current_settings.modeswitches,m_mac);
  907. parse_only:=true;
  908. { generate now the global symboltable,
  909. define first as local to overcome dependency conflicts }
  910. current_module.localsymtable:=tglobalsymtable.create(current_module.modulename^,current_module.moduleid);
  911. { insert unitsym of this unit to prevent other units having
  912. the same name }
  913. current_module.localsymtable.insert(tunitsym.create(current_module.realmodulename^,current_module));
  914. { load default units, like the system unit }
  915. loaddefaultunits;
  916. { insert qualifier for the system unit (allows system.writeln) }
  917. if not(cs_compilesystem in current_settings.moduleswitches) and
  918. (token=_USES) then
  919. begin
  920. loadunits;
  921. { has it been compiled at a higher level ?}
  922. if current_module.state=ms_compiled then
  923. exit;
  924. end;
  925. { move the global symtable from the temporary local to global }
  926. current_module.globalsymtable:=current_module.localsymtable;
  927. current_module.localsymtable:=nil;
  928. reset_all_defs;
  929. { number all units, so we know if a unit is used by this unit or
  930. needs to be added implicitly }
  931. current_module.updatemaps;
  932. { create whole program optimisation information }
  933. current_module.wpoinfo:=tunitwpoinfo.create;
  934. { ... parse the declarations }
  935. Message1(parser_u_parsing_interface,current_module.realmodulename^);
  936. symtablestack.push(current_module.globalsymtable);
  937. read_interface_declarations;
  938. symtablestack.pop(current_module.globalsymtable);
  939. { Export macros defined in the interface for macpas. The macros
  940. are put in the globalmacrosymtable that will only be used by other
  941. units. The current unit continues to use the localmacrosymtable }
  942. if (m_mac in current_settings.modeswitches) then
  943. begin
  944. current_module.globalmacrosymtable:=tmacrosymtable.create(true);
  945. current_module.localmacrosymtable.SymList.ForEachCall(@copy_macro,nil);
  946. end;
  947. { leave when we got an error }
  948. if (Errorcount>0) and not status.skip_error then
  949. begin
  950. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  951. status.skip_error:=true;
  952. exit;
  953. end;
  954. { Our interface is compiled, generate CRC and switch to implementation }
  955. if not(cs_compilesystem in current_settings.moduleswitches) and
  956. (Errorcount=0) then
  957. tppumodule(current_module).getppucrc;
  958. current_module.in_interface:=false;
  959. current_module.interface_compiled:=true;
  960. { First reload all units depending on our interface, we need to do this
  961. in the implementation part to prevent erroneous circular references }
  962. reload_flagged_units;
  963. { Parse the implementation section }
  964. if (m_mac in current_settings.modeswitches) and try_to_consume(_END) then
  965. current_module.interface_only:=true
  966. else
  967. current_module.interface_only:=false;
  968. parse_only:=false;
  969. { create static symbol table }
  970. current_module.localsymtable:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
  971. {$ifdef i386}
  972. if cs_create_pic in current_settings.moduleswitches then
  973. begin
  974. { insert symbol for got access in assembler code}
  975. gotvarsym:=tstaticvarsym.create('_GLOBAL_OFFSET_TABLE_',vs_value,voidpointertype,[vo_is_external]);
  976. gotvarsym.set_mangledname('_GLOBAL_OFFSET_TABLE_');
  977. current_module.localsymtable.insert(gotvarsym);
  978. { avoid unnecessary warnings }
  979. gotvarsym.varstate:=vs_read;
  980. gotvarsym.refs:=1;
  981. end;
  982. {$endif i386}
  983. if not current_module.interface_only then
  984. begin
  985. consume(_IMPLEMENTATION);
  986. Message1(unit_u_loading_implementation_units,current_module.modulename^);
  987. { Read the implementation units }
  988. parse_implementation_uses;
  989. end;
  990. if current_module.state=ms_compiled then
  991. exit;
  992. { reset ranges/stabs in exported definitions }
  993. reset_all_defs;
  994. { All units are read, now give them a number }
  995. current_module.updatemaps;
  996. symtablestack.push(current_module.globalsymtable);
  997. symtablestack.push(current_module.localsymtable);
  998. if not current_module.interface_only then
  999. begin
  1000. Message1(parser_u_parsing_implementation,current_module.modulename^);
  1001. if current_module.in_interface then
  1002. internalerror(200212285);
  1003. { Compile the unit }
  1004. init_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'init'),potype_unitinit,current_module.localsymtable);
  1005. init_procinfo.procdef.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
  1006. init_procinfo.parse_body;
  1007. { save file pos for debuginfo }
  1008. current_module.mainfilepos:=init_procinfo.entrypos;
  1009. end;
  1010. { Generate specializations of objectdefs methods }
  1011. generate_specialization_procs;
  1012. { if the unit contains ansi/widestrings, initialization and
  1013. finalization code must be forced }
  1014. force_init_final:=tglobalsymtable(current_module.globalsymtable).needs_init_final or
  1015. tstaticsymtable(current_module.localsymtable).needs_init_final;
  1016. { should we force unit initialization? }
  1017. { this is a hack, but how can it be done better ? }
  1018. if force_init_final and ((current_module.flags and uf_init)=0) then
  1019. begin
  1020. { first release the not used init procinfo }
  1021. if assigned(init_procinfo) then
  1022. release_main_proc(init_procinfo);
  1023. init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable);
  1024. end;
  1025. { finalize? }
  1026. if not current_module.interface_only and (token=_FINALIZATION) then
  1027. begin
  1028. { set module options }
  1029. current_module.flags:=current_module.flags or uf_finalize;
  1030. { Compile the finalize }
  1031. finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
  1032. finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
  1033. finalize_procinfo.parse_body;
  1034. end
  1035. else if force_init_final then
  1036. finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
  1037. { Now both init and finalize bodies are read and it is known
  1038. which variables are used in both init and finalize we can now
  1039. generate the code. This is required to prevent putting a variable in
  1040. a register that is also used in the finalize body (PFV) }
  1041. if assigned(init_procinfo) then
  1042. begin
  1043. init_procinfo.generate_code;
  1044. init_procinfo.resetprocdef;
  1045. release_main_proc(init_procinfo);
  1046. end;
  1047. if assigned(finalize_procinfo) then
  1048. begin
  1049. finalize_procinfo.generate_code;
  1050. finalize_procinfo.resetprocdef;
  1051. release_main_proc(finalize_procinfo);
  1052. end;
  1053. symtablestack.pop(current_module.localsymtable);
  1054. symtablestack.pop(current_module.globalsymtable);
  1055. { the last char should always be a point }
  1056. consume(_POINT);
  1057. if (Errorcount=0) then
  1058. begin
  1059. { tests, if all (interface) forwards are resolved }
  1060. tstoredsymtable(current_module.globalsymtable).check_forwards;
  1061. { check if all private fields are used }
  1062. tstoredsymtable(current_module.globalsymtable).allprivatesused;
  1063. { test static symtable }
  1064. tstoredsymtable(current_module.localsymtable).allsymbolsused;
  1065. tstoredsymtable(current_module.localsymtable).allprivatesused;
  1066. tstoredsymtable(current_module.localsymtable).check_forwards;
  1067. tstoredsymtable(current_module.localsymtable).checklabels;
  1068. { used units }
  1069. current_module.allunitsused;
  1070. end;
  1071. { leave when we got an error }
  1072. if (Errorcount>0) and not status.skip_error then
  1073. begin
  1074. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1075. status.skip_error:=true;
  1076. exit;
  1077. end;
  1078. { if an Objective-C module, generate objc_image_info section }
  1079. MaybeGenerateObjectiveCImageInfo;
  1080. { do we need to add the variants unit? }
  1081. maybeloadvariantsunit;
  1082. { generate wrappers for interfaces }
  1083. gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.globalsymtable);
  1084. gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.localsymtable);
  1085. { generate pic helpers to load eip if necessary }
  1086. gen_pic_helpers(current_asmdata.asmlists[al_procedures]);
  1087. { generate rtti/init tables }
  1088. write_persistent_type_info(current_module.globalsymtable);
  1089. write_persistent_type_info(current_module.localsymtable);
  1090. { Tables }
  1091. insertThreadVars;
  1092. { Resource strings }
  1093. GenerateResourceStrings;
  1094. { generate debuginfo }
  1095. if (cs_debuginfo in current_settings.moduleswitches) then
  1096. current_debuginfo.inserttypeinfo;
  1097. { generate imports }
  1098. if current_module.ImportLibraryList.Count>0 then
  1099. importlib.generatelib;
  1100. { insert own objectfile, or say that it's in a library
  1101. (no check for an .o when loading) }
  1102. ag:=is_assembler_generated;
  1103. if ag then
  1104. insertobjectfile
  1105. else
  1106. begin
  1107. current_module.flags:=current_module.flags or uf_no_link;
  1108. current_module.flags:=current_module.flags and not (uf_has_stabs_debuginfo or uf_has_dwarf_debuginfo);
  1109. end;
  1110. if ag then
  1111. begin
  1112. { create callframe info }
  1113. create_dwarf_frame;
  1114. { assemble }
  1115. create_objectfile;
  1116. end;
  1117. { Write out the ppufile after the object file has been created }
  1118. store_interface_crc:=current_module.interface_crc;
  1119. {$ifdef EXTDEBUG}
  1120. store_crc:=current_module.crc;
  1121. {$endif EXTDEBUG}
  1122. if (Errorcount=0) then
  1123. tppumodule(current_module).writeppu;
  1124. if not(cs_compilesystem in current_settings.moduleswitches) then
  1125. if store_interface_crc<>current_module.interface_crc then
  1126. Message1(unit_u_interface_crc_changed,current_module.ppufilename^);
  1127. {$ifdef EXTDEBUG}
  1128. if not(cs_compilesystem in current_settings.moduleswitches) then
  1129. if (store_crc<>current_module.crc) and simplify_ppu then
  1130. Message1(unit_u_implementation_crc_changed,current_module.ppufilename^);
  1131. {$endif EXTDEBUG}
  1132. { release local symtables that are not needed anymore }
  1133. free_localsymtables(current_module.globalsymtable);
  1134. free_localsymtables(current_module.localsymtable);
  1135. { leave when we got an error }
  1136. if (Errorcount>0) and not status.skip_error then
  1137. begin
  1138. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1139. status.skip_error:=true;
  1140. exit;
  1141. end;
  1142. {$ifdef debug_devirt}
  1143. { print out all instantiated class/object types }
  1144. writeln('constructed object/class/classreftypes in ',current_module.realmodulename^);
  1145. for i := 0 to current_module.wpoinfo.createdobjtypes.count-1 do
  1146. begin
  1147. write(' ',tdef(current_module.wpoinfo.createdobjtypes[i]).GetTypeName);
  1148. case tdef(current_module.wpoinfo.createdobjtypes[i]).typ of
  1149. objectdef:
  1150. case tobjectdef(current_module.wpoinfo.createdobjtypes[i]).objecttype of
  1151. odt_object:
  1152. writeln(' (object)');
  1153. odt_class:
  1154. writeln(' (class)');
  1155. else
  1156. internalerror(2008101103);
  1157. end;
  1158. else
  1159. internalerror(2008101104);
  1160. end;
  1161. end;
  1162. for i := 0 to current_module.wpoinfo.createdclassrefobjtypes.count-1 do
  1163. begin
  1164. write(' Class Of ',tdef(current_module.wpoinfo.createdclassrefobjtypes[i]).GetTypeName);
  1165. case tdef(current_module.wpoinfo.createdclassrefobjtypes[i]).typ of
  1166. objectdef:
  1167. case tobjectdef(current_module.wpoinfo.createdclassrefobjtypes[i]).objecttype of
  1168. odt_class:
  1169. writeln(' (classrefdef)');
  1170. else
  1171. internalerror(2008101105);
  1172. end
  1173. else
  1174. internalerror(2008101102);
  1175. end;
  1176. end;
  1177. {$endif debug_devirt}
  1178. Message1(unit_u_finished_compiling,current_module.modulename^);
  1179. end;
  1180. procedure procexport(const s : string);
  1181. var
  1182. hp : texported_item;
  1183. begin
  1184. hp:=texported_item.create;
  1185. hp.name:=stringdup(s);
  1186. hp.options:=hp.options or eo_name;
  1187. exportlib.exportprocedure(hp);
  1188. end;
  1189. procedure varexport(const s : string);
  1190. var
  1191. hp : texported_item;
  1192. begin
  1193. hp:=texported_item.create;
  1194. hp.name:=stringdup(s);
  1195. hp.options:=hp.options or eo_name;
  1196. exportlib.exportvar(hp);
  1197. end;
  1198. procedure insert_export(sym : TObject;arg:pointer);
  1199. var
  1200. i : longint;
  1201. item : TCmdStrListItem;
  1202. begin
  1203. case TSym(sym).typ of
  1204. { ignore: }
  1205. unitsym,
  1206. syssym,
  1207. constsym,
  1208. enumsym,
  1209. typesym:
  1210. ;
  1211. procsym:
  1212. begin
  1213. for i:=0 to tprocsym(sym).ProcdefList.Count-1 do
  1214. begin
  1215. if not(tprocdef(tprocsym(sym).ProcdefList[i]).proccalloption in [pocall_internproc]) and
  1216. ((tprocdef(tprocsym(sym).ProcdefList[i]).procoptions*[po_external])=[]) and
  1217. ((tsymtable(arg).symtabletype=globalsymtable) or
  1218. ((tsymtable(arg).symtabletype=staticsymtable) and (po_public in tprocdef(tprocsym(sym).ProcdefList[i]).procoptions))
  1219. ) then
  1220. begin
  1221. procexport(tprocdef(tprocsym(sym).ProcdefList[i]).mangledname);
  1222. { walk through all aliases }
  1223. item:=TCmdStrListItem(tprocdef(tprocsym(sym).ProcdefList[i]).aliasnames.first);
  1224. while assigned(item) do
  1225. begin
  1226. { avoid duplicate entries, sometimes aliasnames contains the mangledname }
  1227. if item.str<>tprocdef(tprocsym(sym).ProcdefList[i]).mangledname then
  1228. procexport(item.str);
  1229. item:=TCmdStrListItem(item.next);
  1230. end;
  1231. end;
  1232. end;
  1233. end;
  1234. staticvarsym:
  1235. begin
  1236. varexport(tsym(sym).mangledname);
  1237. end;
  1238. else
  1239. begin
  1240. writeln('unknown: ',ord(TSym(sym).typ));
  1241. end;
  1242. end;
  1243. end;
  1244. Function RewritePPU(const PPUFn,PPLFn:String):Boolean;
  1245. Var
  1246. MakeStatic : Boolean;
  1247. Var
  1248. buffer : array[0..$1fff] of byte;
  1249. inppu,
  1250. outppu : tppufile;
  1251. b,
  1252. untilb : byte;
  1253. l,m : longint;
  1254. f : file;
  1255. ext,
  1256. s : string;
  1257. ppuversion : dword;
  1258. begin
  1259. Result:=false;
  1260. MakeStatic:=False;
  1261. inppu:=tppufile.create(PPUFn);
  1262. if not inppu.openfile then
  1263. begin
  1264. inppu.free;
  1265. Comment(V_Error,'Could not open : '+PPUFn);
  1266. Exit;
  1267. end;
  1268. { Check the ppufile }
  1269. if not inppu.CheckPPUId then
  1270. begin
  1271. inppu.free;
  1272. Comment(V_Error,'Not a PPU File : '+PPUFn);
  1273. Exit;
  1274. end;
  1275. ppuversion:=inppu.GetPPUVersion;
  1276. if ppuversion<CurrentPPUVersion then
  1277. begin
  1278. inppu.free;
  1279. Comment(V_Error,'Wrong PPU Version '+tostr(ppuversion)+' in '+PPUFn);
  1280. Exit;
  1281. end;
  1282. { No .o file generated for this ppu, just skip }
  1283. if (inppu.header.flags and uf_no_link)<>0 then
  1284. begin
  1285. inppu.free;
  1286. Result:=true;
  1287. Exit;
  1288. end;
  1289. { Already a lib? }
  1290. if (inppu.header.flags and uf_in_library)<>0 then
  1291. begin
  1292. inppu.free;
  1293. Comment(V_Error,'PPU is already in a library : '+PPUFn);
  1294. Exit;
  1295. end;
  1296. { We need a static linked unit }
  1297. if (inppu.header.flags and uf_static_linked)=0 then
  1298. begin
  1299. inppu.free;
  1300. Comment(V_Error,'PPU is not static linked : '+PPUFn);
  1301. Exit;
  1302. end;
  1303. { Check if shared is allowed }
  1304. if tsystem(inppu.header.target) in [system_i386_go32v2] then
  1305. begin
  1306. Comment(V_Error,'Shared library not supported for ppu target, switching to static library');
  1307. MakeStatic:=true;
  1308. end;
  1309. { Create the new ppu }
  1310. if PPUFn=PPLFn then
  1311. outppu:=tppufile.create('ppumove.$$$')
  1312. else
  1313. outppu:=tppufile.create(PPLFn);
  1314. outppu.createfile;
  1315. { Create new header, with the new flags }
  1316. outppu.header:=inppu.header;
  1317. outppu.header.flags:=outppu.header.flags or uf_in_library;
  1318. if MakeStatic then
  1319. outppu.header.flags:=outppu.header.flags or uf_static_linked
  1320. else
  1321. outppu.header.flags:=outppu.header.flags or uf_shared_linked;
  1322. { read until the object files are found }
  1323. untilb:=iblinkunitofiles;
  1324. repeat
  1325. b:=inppu.readentry;
  1326. if b in [ibendinterface,ibend] then
  1327. begin
  1328. inppu.free;
  1329. outppu.free;
  1330. Comment(V_Error,'No files to be linked found : '+PPUFn);
  1331. Exit;
  1332. end;
  1333. if b<>untilb then
  1334. begin
  1335. repeat
  1336. inppu.getdatabuf(buffer,sizeof(buffer),l);
  1337. outppu.putdata(buffer,l);
  1338. until l<sizeof(buffer);
  1339. outppu.writeentry(b);
  1340. end;
  1341. until (b=untilb);
  1342. { we have now reached the section for the files which need to be added,
  1343. now add them to the list }
  1344. case b of
  1345. iblinkunitofiles :
  1346. begin
  1347. { add all o files, and save the entry when not creating a static
  1348. library to keep staticlinking possible }
  1349. while not inppu.endofentry do
  1350. begin
  1351. s:=inppu.getstring;
  1352. m:=inppu.getlongint;
  1353. if not MakeStatic then
  1354. begin
  1355. outppu.putstring(s);
  1356. outppu.putlongint(m);
  1357. end;
  1358. current_module.linkotherofiles.add(s,link_always);;
  1359. end;
  1360. if not MakeStatic then
  1361. outppu.writeentry(b);
  1362. end;
  1363. { iblinkunitstaticlibs :
  1364. begin
  1365. AddToLinkFiles(ExtractLib(inppu.getstring));
  1366. if not inppu.endofentry then
  1367. begin
  1368. repeat
  1369. inppu.getdatabuf(buffer^,bufsize,l);
  1370. outppu.putdata(buffer^,l);
  1371. until l<bufsize;
  1372. outppu.writeentry(b);
  1373. end;
  1374. end; }
  1375. end;
  1376. { just add a new entry with the new lib }
  1377. if MakeStatic then
  1378. begin
  1379. outppu.putstring('imp'+current_module.realmodulename^);
  1380. outppu.putlongint(link_static);
  1381. outppu.writeentry(iblinkunitstaticlibs)
  1382. end
  1383. else
  1384. begin
  1385. outppu.putstring('imp'+current_module.realmodulename^);
  1386. outppu.putlongint(link_shared);
  1387. outppu.writeentry(iblinkunitsharedlibs);
  1388. end;
  1389. { read all entries until the end and write them also to the new ppu }
  1390. repeat
  1391. b:=inppu.readentry;
  1392. { don't write ibend, that's written automaticly }
  1393. if b<>ibend then
  1394. begin
  1395. if b=iblinkothersharedlibs then
  1396. begin
  1397. while not inppu.endofentry do
  1398. begin
  1399. s:=inppu.getstring;
  1400. m:=inppu.getlongint;
  1401. outppu.putstring(s);
  1402. outppu.putlongint(m);
  1403. { strip lib prefix }
  1404. if copy(s,1,3)='lib' then
  1405. delete(s,1,3);
  1406. ext:=ExtractFileExt(s);
  1407. if ext<>'' then
  1408. delete(s,length(s)-length(ext)+1,length(ext));
  1409. current_module.linkOtherSharedLibs.add(s,link_always);
  1410. end;
  1411. end
  1412. else
  1413. repeat
  1414. inppu.getdatabuf(buffer,sizeof(buffer),l);
  1415. outppu.putdata(buffer,l);
  1416. until l<sizeof(buffer);
  1417. outppu.writeentry(b);
  1418. end;
  1419. until b=ibend;
  1420. { write the last stuff and close }
  1421. outppu.flush;
  1422. outppu.writeheader;
  1423. outppu.free;
  1424. inppu.free;
  1425. { rename }
  1426. if PPUFn=PPLFn then
  1427. begin
  1428. {$I-}
  1429. assign(f,PPUFn);
  1430. erase(f);
  1431. assign(f,'ppumove.$$$');
  1432. rename(f,PPUFn);
  1433. {$I+}
  1434. if ioresult<>0 then;
  1435. end;
  1436. Result:=True;
  1437. end;
  1438. procedure createimportlibfromexports;
  1439. var
  1440. hp : texported_item;
  1441. begin
  1442. hp:=texported_item(current_module._exports.first);
  1443. while assigned(hp) do
  1444. begin
  1445. current_module.AddExternalImport(current_module.realmodulename^,hp.name^,hp.index,hp.is_var,false);
  1446. hp:=texported_item(hp.next);
  1447. end;
  1448. end;
  1449. procedure proc_package;
  1450. var
  1451. main_file : tinputfile;
  1452. hp,hp2 : tmodule;
  1453. {finalize_procinfo,
  1454. init_procinfo,
  1455. main_procinfo : tcgprocinfo;}
  1456. force_init_final : boolean;
  1457. uu : tused_unit;
  1458. begin
  1459. Status.IsPackage:=true;
  1460. Status.IsExe:=true;
  1461. parse_only:=false;
  1462. {main_procinfo:=nil;
  1463. init_procinfo:=nil;
  1464. finalize_procinfo:=nil;}
  1465. if not RelocSectionSetExplicitly then
  1466. RelocSection:=true;
  1467. { Relocation works only without stabs under Windows when }
  1468. { external linker (LD) is used. LD generates relocs for }
  1469. { stab sections which is not loaded in memory. It causes }
  1470. { AV error when DLL is loaded and relocation is needed. }
  1471. { Internal linker does not have this problem. }
  1472. if RelocSection and
  1473. (target_info.system in system_all_windows+[system_i386_wdosx]) and
  1474. (cs_link_extern in current_settings.globalswitches) then
  1475. begin
  1476. include(current_settings.globalswitches,cs_link_strip);
  1477. { Warning stabs info does not work with reloc section !! }
  1478. if (cs_debuginfo in current_settings.moduleswitches) and
  1479. (target_dbg.id=dbg_stabs) then
  1480. begin
  1481. Message1(parser_w_parser_reloc_no_debug,current_module.mainsource^);
  1482. Message(parser_w_parser_win32_debug_needs_WN);
  1483. exclude(current_settings.moduleswitches,cs_debuginfo);
  1484. end;
  1485. end;
  1486. { get correct output names }
  1487. main_file := current_scanner.inputfile;
  1488. while assigned(main_file.next) do
  1489. main_file := main_file.next;
  1490. current_module.SetFileName(main_file.path^+main_file.name^,true);
  1491. consume(_ID);
  1492. current_module.setmodulename(orgpattern);
  1493. current_module.ispackage:=true;
  1494. exportlib.preparelib(orgpattern);
  1495. if tf_library_needs_pic in target_info.flags then
  1496. include(current_settings.moduleswitches,cs_create_pic);
  1497. consume(_ID);
  1498. consume(_SEMICOLON);
  1499. { global switches are read, so further changes aren't allowed }
  1500. current_module.in_global:=false;
  1501. { setup things using the switches }
  1502. setupglobalswitches;
  1503. { set implementation flag }
  1504. current_module.in_interface:=false;
  1505. current_module.interface_compiled:=true;
  1506. { insert after the unit symbol tables the static symbol table }
  1507. { of the program }
  1508. current_module.localsymtable:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
  1509. {Load the units used by the program we compile.}
  1510. if token=_REQUIRES then
  1511. begin
  1512. end;
  1513. {Load the units used by the program we compile.}
  1514. if (token=_ID) and (idtoken=_CONTAINS) then
  1515. begin
  1516. consume(_ID);
  1517. while true do
  1518. begin
  1519. if token=_ID then
  1520. AddUnit(pattern);
  1521. consume(_ID);
  1522. if token=_COMMA then
  1523. consume(_COMMA)
  1524. else break;
  1525. end;
  1526. consume(_SEMICOLON);
  1527. end;
  1528. { reset ranges/stabs in exported definitions }
  1529. reset_all_defs;
  1530. { All units are read, now give them a number }
  1531. current_module.updatemaps;
  1532. {Insert the name of the main program into the symbol table.}
  1533. if current_module.realmodulename^<>'' then
  1534. current_module.localsymtable.insert(tunitsym.create(current_module.realmodulename^,current_module));
  1535. Message1(parser_u_parsing_implementation,current_module.mainsource^);
  1536. symtablestack.push(current_module.localsymtable);
  1537. { create whole program optimisation information }
  1538. current_module.wpoinfo:=tunitwpoinfo.create;
  1539. { should we force unit initialization? }
  1540. force_init_final:=tstaticsymtable(current_module.localsymtable).needs_init_final;
  1541. if force_init_final then
  1542. {init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable)};
  1543. { Add symbol to the exports section for win32 so smartlinking a
  1544. DLL will include the edata section }
  1545. if assigned(exportlib) and
  1546. (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1547. ((current_module.flags and uf_has_exports)<>0) then
  1548. current_asmdata.asmlists[al_procedures].concat(tai_const.createname(make_mangledname('EDATA',current_module.localsymtable,''),0));
  1549. { all labels must be defined before generating code }
  1550. if Errorcount=0 then
  1551. tstoredsymtable(current_module.localsymtable).checklabels;
  1552. symtablestack.pop(current_module.localsymtable);
  1553. { consume the last point }
  1554. consume(_END);
  1555. consume(_POINT);
  1556. if (Errorcount=0) then
  1557. begin
  1558. { test static symtable }
  1559. tstoredsymtable(current_module.localsymtable).allsymbolsused;
  1560. tstoredsymtable(current_module.localsymtable).allprivatesused;
  1561. tstoredsymtable(current_module.localsymtable).check_forwards;
  1562. current_module.allunitsused;
  1563. end;
  1564. new_section(current_asmdata.asmlists[al_globals],sec_data,'_FPCDummy',4);
  1565. current_asmdata.asmlists[al_globals].concat(tai_symbol.createname_global('_FPCDummy',AT_DATA,0));
  1566. current_asmdata.asmlists[al_globals].concat(tai_const.create_32bit(0));
  1567. new_section(current_asmdata.asmlists[al_procedures],sec_code,'',0);
  1568. current_asmdata.asmlists[al_procedures].concat(tai_symbol.createname_global('_DLLMainCRTStartup',AT_FUNCTION,0));
  1569. {$ifdef i386}
  1570. { fix me! }
  1571. current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_const_reg(A_MOV,S_L,1,NR_EAX));
  1572. current_asmdata.asmlists[al_procedures].concat(Taicpu.Op_const(A_RET,S_W,12));
  1573. {$endif i386}
  1574. current_asmdata.asmlists[al_procedures].concat(tai_const.createname('_FPCDummy',0));
  1575. { leave when we got an error }
  1576. if (Errorcount>0) and not status.skip_error then
  1577. begin
  1578. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1579. status.skip_error:=true;
  1580. exit;
  1581. end;
  1582. { remove all unused units, this happends when units are removed
  1583. from the uses clause in the source and the ppu was already being loaded }
  1584. hp:=tmodule(loaded_units.first);
  1585. while assigned(hp) do
  1586. begin
  1587. hp2:=hp;
  1588. hp:=tmodule(hp.next);
  1589. if hp2.is_unit and
  1590. not assigned(hp2.globalsymtable) then
  1591. loaded_units.remove(hp2);
  1592. end;
  1593. { force exports }
  1594. uu:=tused_unit(usedunits.first);
  1595. while assigned(uu) do
  1596. begin
  1597. uu.u.globalsymtable.symlist.ForEachCall(@insert_export,uu.u.globalsymtable);
  1598. { check localsymtable for exports too to get public symbols }
  1599. uu.u.localsymtable.symlist.ForEachCall(@insert_export,uu.u.localsymtable);
  1600. { create special exports }
  1601. if (uu.u.flags and uf_init)<>0 then
  1602. procexport(make_mangledname('INIT$',uu.u.globalsymtable,''));
  1603. if (uu.u.flags and uf_finalize)<>0 then
  1604. procexport(make_mangledname('FINALIZE$',uu.u.globalsymtable,''));
  1605. if (uu.u.flags and uf_threadvars)=uf_threadvars then
  1606. varexport(make_mangledname('THREADVARLIST',uu.u.globalsymtable,''));
  1607. uu:=tused_unit(uu.next);
  1608. end;
  1609. {$ifdef arm}
  1610. { Insert .pdata section for arm-wince.
  1611. It is needed for exception handling. }
  1612. if target_info.system in [system_arm_wince] then
  1613. InsertPData;
  1614. {$endif arm}
  1615. { generate debuginfo }
  1616. if (cs_debuginfo in current_settings.moduleswitches) then
  1617. current_debuginfo.inserttypeinfo;
  1618. exportlib.generatelib;
  1619. { write all our exports to the import library,
  1620. needs to be done after exportlib.generatelib; }
  1621. createimportlibfromexports;
  1622. { generate imports }
  1623. if current_module.ImportLibraryList.Count>0 then
  1624. importlib.generatelib;
  1625. { Reference all DEBUGINFO sections from the main .fpc section }
  1626. if (cs_debuginfo in current_settings.moduleswitches) then
  1627. current_debuginfo.referencesections(current_asmdata.asmlists[al_procedures]);
  1628. { insert own objectfile }
  1629. insertobjectfile;
  1630. { assemble and link }
  1631. create_objectfile;
  1632. { We might need the symbols info if not using
  1633. the default do_extractsymbolinfo
  1634. which is a dummy function PM }
  1635. needsymbolinfo:=do_extractsymbolinfo<>@def_extractsymbolinfo;
  1636. { release all local symtables that are not needed anymore }
  1637. if (not needsymbolinfo) then
  1638. free_localsymtables(current_module.localsymtable);
  1639. { leave when we got an error }
  1640. if (Errorcount>0) and not status.skip_error then
  1641. begin
  1642. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1643. status.skip_error:=true;
  1644. exit;
  1645. end;
  1646. if (not current_module.is_unit) then
  1647. begin
  1648. { finally rewrite all units included into the package }
  1649. uu:=tused_unit(usedunits.first);
  1650. while assigned(uu) do
  1651. begin
  1652. RewritePPU(uu.u.ppufilename^,uu.u.ppufilename^);
  1653. uu:=tused_unit(uu.next);
  1654. end;
  1655. { create the executable when we are at level 1 }
  1656. if (compile_level=1) then
  1657. begin
  1658. { create global resource file by collecting all resource files }
  1659. CollectResourceFiles;
  1660. { write .def file }
  1661. if (cs_link_deffile in current_settings.globalswitches) then
  1662. deffile.writefile;
  1663. { insert all .o files from all loaded units and
  1664. unload the units, we don't need them anymore.
  1665. Keep the current_module because that is still needed }
  1666. hp:=tmodule(loaded_units.first);
  1667. while assigned(hp) do
  1668. begin
  1669. { the package itself contains no code so far }
  1670. linker.AddModuleFiles(hp);
  1671. hp2:=tmodule(hp.next);
  1672. if (hp<>current_module) and
  1673. (not needsymbolinfo) then
  1674. begin
  1675. loaded_units.remove(hp);
  1676. hp.free;
  1677. end;
  1678. hp:=hp2;
  1679. end;
  1680. linker.MakeSharedLibrary
  1681. end;
  1682. { Give Fatal with error count for linker errors }
  1683. if (Errorcount>0) and not status.skip_error then
  1684. begin
  1685. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1686. status.skip_error:=true;
  1687. end;
  1688. end;
  1689. end;
  1690. procedure proc_program(islibrary : boolean);
  1691. var
  1692. main_file : tinputfile;
  1693. hp,hp2 : tmodule;
  1694. finalize_procinfo,
  1695. init_procinfo,
  1696. main_procinfo : tcgprocinfo;
  1697. force_init_final : boolean;
  1698. resources_used : boolean;
  1699. begin
  1700. DLLsource:=islibrary;
  1701. Status.IsLibrary:=IsLibrary;
  1702. Status.IsPackage:=false;
  1703. Status.IsExe:=true;
  1704. parse_only:=false;
  1705. main_procinfo:=nil;
  1706. init_procinfo:=nil;
  1707. finalize_procinfo:=nil;
  1708. resources_used:=false;
  1709. { DLL defaults to create reloc info }
  1710. if islibrary then
  1711. begin
  1712. if not RelocSectionSetExplicitly then
  1713. RelocSection:=true;
  1714. end;
  1715. { Relocation works only without stabs under Windows when }
  1716. { external linker (LD) is used. LD generates relocs for }
  1717. { stab sections which is not loaded in memory. It causes }
  1718. { AV error when DLL is loaded and relocation is needed. }
  1719. { Internal linker does not have this problem. }
  1720. if RelocSection and
  1721. (target_info.system in system_all_windows+[system_i386_wdosx]) and
  1722. (cs_link_extern in current_settings.globalswitches) then
  1723. begin
  1724. include(current_settings.globalswitches,cs_link_strip);
  1725. { Warning stabs info does not work with reloc section !! }
  1726. if (cs_debuginfo in current_settings.moduleswitches) and
  1727. (target_dbg.id=dbg_stabs) then
  1728. begin
  1729. Message1(parser_w_parser_reloc_no_debug,current_module.mainsource^);
  1730. Message(parser_w_parser_win32_debug_needs_WN);
  1731. exclude(current_settings.moduleswitches,cs_debuginfo);
  1732. end;
  1733. end;
  1734. { get correct output names }
  1735. main_file := current_scanner.inputfile;
  1736. while assigned(main_file.next) do
  1737. main_file := main_file.next;
  1738. current_module.SetFileName(main_file.path^+main_file.name^,true);
  1739. if islibrary then
  1740. begin
  1741. consume(_LIBRARY);
  1742. current_module.setmodulename(orgpattern);
  1743. current_module.islibrary:=true;
  1744. exportlib.preparelib(orgpattern);
  1745. if tf_library_needs_pic in target_info.flags then
  1746. include(current_settings.moduleswitches,cs_create_pic);
  1747. consume(_ID);
  1748. consume(_SEMICOLON);
  1749. end
  1750. else
  1751. { is there an program head ? }
  1752. if token=_PROGRAM then
  1753. begin
  1754. consume(_PROGRAM);
  1755. current_module.setmodulename(orgpattern);
  1756. if (target_info.system in system_unit_program_exports) then
  1757. exportlib.preparelib(orgpattern);
  1758. consume(_ID);
  1759. if token=_LKLAMMER then
  1760. begin
  1761. consume(_LKLAMMER);
  1762. repeat
  1763. consume(_ID);
  1764. until not try_to_consume(_COMMA);
  1765. consume(_RKLAMMER);
  1766. end;
  1767. consume(_SEMICOLON);
  1768. end
  1769. else if (target_info.system in system_unit_program_exports) then
  1770. exportlib.preparelib(current_module.realmodulename^);
  1771. { global switches are read, so further changes aren't allowed }
  1772. current_module.in_global:=false;
  1773. { setup things using the switches }
  1774. setupglobalswitches;
  1775. { set implementation flag }
  1776. current_module.in_interface:=false;
  1777. current_module.interface_compiled:=true;
  1778. { insert after the unit symbol tables the static symbol table }
  1779. { of the program }
  1780. current_module.localsymtable:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
  1781. { load standard units (system,objpas,profile unit) }
  1782. loaddefaultunits;
  1783. { Load units provided on the command line }
  1784. loadautounits;
  1785. {Load the units used by the program we compile.}
  1786. if token=_USES then
  1787. loadunits;
  1788. { reset ranges/stabs in exported definitions }
  1789. reset_all_defs;
  1790. { All units are read, now give them a number }
  1791. current_module.updatemaps;
  1792. {Insert the name of the main program into the symbol table.}
  1793. if current_module.realmodulename^<>'' then
  1794. current_module.localsymtable.insert(tunitsym.create(current_module.realmodulename^,current_module));
  1795. Message1(parser_u_parsing_implementation,current_module.mainsource^);
  1796. symtablestack.push(current_module.localsymtable);
  1797. { create whole program optimisation information }
  1798. current_module.wpoinfo:=tunitwpoinfo.create;
  1799. { The program intialization needs an alias, so it can be called
  1800. from the bootstrap code.}
  1801. if islibrary then
  1802. begin
  1803. main_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,mainaliasname),potype_proginit,current_module.localsymtable);
  1804. { Win32 startup code needs a single name }
  1805. if not(target_info.system in systems_darwin) then
  1806. main_procinfo.procdef.aliasnames.insert('PASCALMAIN')
  1807. else
  1808. main_procinfo.procdef.aliasnames.insert(target_info.Cprefix+'PASCALMAIN')
  1809. end
  1810. else if (target_info.system in ([system_i386_netware,system_i386_netwlibc,system_powerpc_macos]+systems_darwin)) then
  1811. begin
  1812. main_procinfo:=create_main_proc('PASCALMAIN',potype_proginit,current_module.localsymtable);
  1813. end
  1814. else
  1815. begin
  1816. main_procinfo:=create_main_proc(mainaliasname,potype_proginit,current_module.localsymtable);
  1817. main_procinfo.procdef.aliasnames.insert('PASCALMAIN');
  1818. end;
  1819. main_procinfo.parse_body;
  1820. { save file pos for debuginfo }
  1821. current_module.mainfilepos:=main_procinfo.entrypos;
  1822. { Generate specializations of objectdefs methods }
  1823. generate_specialization_procs;
  1824. { should we force unit initialization? }
  1825. force_init_final:=tstaticsymtable(current_module.localsymtable).needs_init_final;
  1826. if force_init_final then
  1827. init_procinfo:=gen_implicit_initfinal(uf_init,current_module.localsymtable);
  1828. { Add symbol to the exports section for win32 so smartlinking a
  1829. DLL will include the edata section }
  1830. if assigned(exportlib) and
  1831. (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1832. ((current_module.flags and uf_has_exports)<>0) then
  1833. current_asmdata.asmlists[al_procedures].concat(tai_const.createname(make_mangledname('EDATA',current_module.localsymtable,''),0));
  1834. { finalize? }
  1835. if token=_FINALIZATION then
  1836. begin
  1837. { set module options }
  1838. current_module.flags:=current_module.flags or uf_finalize;
  1839. { Parse the finalize }
  1840. finalize_procinfo:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,current_module.localsymtable);
  1841. finalize_procinfo.procdef.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
  1842. finalize_procinfo.procdef.aliasnames.insert('PASCALFINALIZE');
  1843. finalize_procinfo.parse_body;
  1844. end
  1845. else
  1846. if force_init_final then
  1847. finalize_procinfo:=gen_implicit_initfinal(uf_finalize,current_module.localsymtable);
  1848. { the finalization routine of libraries is generic (and all libraries need to }
  1849. { be finalized, so they can finalize any units they use }
  1850. if (islibrary) then
  1851. exportlib.setfininame(current_asmdata.asmlists[al_procedures],'FPC_LIB_EXIT');
  1852. { all labels must be defined before generating code }
  1853. if Errorcount=0 then
  1854. tstoredsymtable(current_module.localsymtable).checklabels;
  1855. { See remark in unit init/final }
  1856. main_procinfo.generate_code;
  1857. main_procinfo.resetprocdef;
  1858. release_main_proc(main_procinfo);
  1859. if assigned(init_procinfo) then
  1860. begin
  1861. init_procinfo.generate_code;
  1862. init_procinfo.resetprocdef;
  1863. release_main_proc(init_procinfo);
  1864. end;
  1865. if assigned(finalize_procinfo) then
  1866. begin
  1867. finalize_procinfo.generate_code;
  1868. finalize_procinfo.resetprocdef;
  1869. release_main_proc(finalize_procinfo);
  1870. end;
  1871. symtablestack.pop(current_module.localsymtable);
  1872. { consume the last point }
  1873. consume(_POINT);
  1874. if (Errorcount=0) then
  1875. begin
  1876. { test static symtable }
  1877. tstoredsymtable(current_module.localsymtable).allsymbolsused;
  1878. tstoredsymtable(current_module.localsymtable).allprivatesused;
  1879. tstoredsymtable(current_module.localsymtable).check_forwards;
  1880. current_module.allunitsused;
  1881. end;
  1882. { leave when we got an error }
  1883. if (Errorcount>0) and not status.skip_error then
  1884. begin
  1885. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1886. status.skip_error:=true;
  1887. exit;
  1888. end;
  1889. { remove all unused units, this happens when units are removed
  1890. from the uses clause in the source and the ppu was already being loaded }
  1891. hp:=tmodule(loaded_units.first);
  1892. while assigned(hp) do
  1893. begin
  1894. hp2:=hp;
  1895. hp:=tmodule(hp.next);
  1896. if hp2.is_unit and
  1897. not assigned(hp2.globalsymtable) then
  1898. begin
  1899. loaded_units.remove(hp2);
  1900. unloaded_units.concat(hp2);
  1901. end;
  1902. end;
  1903. { if an Objective-C module, generate objc_image_info section }
  1904. MaybeGenerateObjectiveCImageInfo;
  1905. { do we need to add the variants unit? }
  1906. maybeloadvariantsunit;
  1907. { Now that everything has been compiled we know if we need resource
  1908. support. If not, remove the unit. }
  1909. resources_used:=MaybeRemoveResUnit;
  1910. linker.initsysinitunitname;
  1911. if target_info.system in system_internal_sysinit then
  1912. begin
  1913. { add start/halt unit }
  1914. AddUnit(linker.sysinitunit);
  1915. end;
  1916. {$ifdef arm}
  1917. { Insert .pdata section for arm-wince.
  1918. It is needed for exception handling. }
  1919. if target_info.system in [system_arm_wince] then
  1920. InsertPData;
  1921. {$endif arm}
  1922. InsertThreadvars;
  1923. { generate pic helpers to load eip if necessary }
  1924. gen_pic_helpers(current_asmdata.asmlists[al_procedures]);
  1925. { generate rtti/init tables }
  1926. write_persistent_type_info(current_module.localsymtable);
  1927. { generate wrappers for interfaces }
  1928. gen_intf_wrappers(current_asmdata.asmlists[al_procedures],current_module.localsymtable);
  1929. { generate imports }
  1930. if current_module.ImportLibraryList.Count>0 then
  1931. importlib.generatelib;
  1932. { generate debuginfo }
  1933. if (cs_debuginfo in current_settings.moduleswitches) then
  1934. current_debuginfo.inserttypeinfo;
  1935. if islibrary or (target_info.system in system_unit_program_exports) then
  1936. exportlib.generatelib;
  1937. { Reference all DEBUGINFO sections from the main .fpc section }
  1938. if (cs_debuginfo in current_settings.moduleswitches) then
  1939. current_debuginfo.referencesections(current_asmdata.asmlists[al_procedures]);
  1940. { Resource strings }
  1941. GenerateResourceStrings;
  1942. { insert Tables and StackLength }
  1943. insertinitfinaltable;
  1944. InsertThreadvarTablesTable;
  1945. InsertResourceTablesTable;
  1946. insertmemorysizes;
  1947. { Insert symbol to resource info }
  1948. InsertResourceInfo(resources_used);
  1949. { create callframe info }
  1950. create_dwarf_frame;
  1951. { insert own objectfile }
  1952. insertobjectfile;
  1953. { assemble and link }
  1954. create_objectfile;
  1955. { We might need the symbols info if not using
  1956. the default do_extractsymbolinfo
  1957. which is a dummy function PM }
  1958. needsymbolinfo:=
  1959. (do_extractsymbolinfo<>@def_extractsymbolinfo) or
  1960. ((current_settings.genwpoptimizerswitches*WPOptimizationsNeedingAllUnitInfo)<>[]);
  1961. { release all local symtables that are not needed anymore }
  1962. if (not needsymbolinfo) then
  1963. free_localsymtables(current_module.localsymtable);
  1964. { leave when we got an error }
  1965. if (Errorcount>0) and not status.skip_error then
  1966. begin
  1967. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1968. status.skip_error:=true;
  1969. exit;
  1970. end;
  1971. if (not current_module.is_unit) then
  1972. begin
  1973. { create the executable when we are at level 1 }
  1974. if (compile_level=1) then
  1975. begin
  1976. { create global resource file by collecting all resource files }
  1977. CollectResourceFiles;
  1978. { write .def file }
  1979. if (cs_link_deffile in current_settings.globalswitches) then
  1980. deffile.writefile;
  1981. { insert all .o files from all loaded units and
  1982. unload the units, we don't need them anymore.
  1983. Keep the current_module because that is still needed }
  1984. hp:=tmodule(loaded_units.first);
  1985. while assigned(hp) do
  1986. begin
  1987. linker.AddModuleFiles(hp);
  1988. hp2:=tmodule(hp.next);
  1989. if (hp<>current_module) and
  1990. (not needsymbolinfo) then
  1991. begin
  1992. loaded_units.remove(hp);
  1993. hp.free;
  1994. end;
  1995. hp:=hp2;
  1996. end;
  1997. { free also unneeded units we didn't free before }
  1998. if not needsymbolinfo then
  1999. unloaded_units.Clear;
  2000. { finally we can create a executable }
  2001. if DLLSource then
  2002. linker.MakeSharedLibrary
  2003. else
  2004. linker.MakeExecutable;
  2005. { collect all necessary information for whole-program optimization }
  2006. wpoinfomanager.extractwpoinfofromprogram;
  2007. end;
  2008. { Give Fatal with error count for linker errors }
  2009. if (Errorcount>0) and not status.skip_error then
  2010. begin
  2011. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  2012. status.skip_error:=true;
  2013. end;
  2014. end;
  2015. end;
  2016. end.