pmodules.pas 77 KB

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