pmodules.pas 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717
  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_program(islibrary : boolean);
  22. implementation
  23. uses
  24. globtype,version,systems,tokens,
  25. cutils,cclasses,comphook,
  26. globals,verbose,fmodule,finput,fppu,
  27. symconst,symbase,symtype,symdef,symsym,symtable,
  28. aasmtai,aasmcpu,aasmbase,
  29. cgbase,cgobj,
  30. nbas,ncgutil,
  31. link,assemble,import,export,gendef,ppu,comprsrc,dbgbase,
  32. cresstr,procinfo,
  33. dwarf,pexports,
  34. {$ifdef GDB}
  35. gdb,
  36. {$endif GDB}
  37. scanner,pbase,pexpr,psystem,psub,pdecsub;
  38. (*
  39. procedure fixseg(p:TAAsmoutput; sec:TAsmSectionType; secname: string);
  40. begin
  41. maybe_new_object_file(p);
  42. if target_info.system <> system_powerpc_macos then
  43. p.insert(Tai_section.Create(sec,'',0))
  44. else
  45. p.insert(Tai_section.Create(sec,secname,0));
  46. end;
  47. *)
  48. procedure create_objectfile;
  49. var
  50. DLLScanner : TDLLScanner;
  51. s : string;
  52. KeepShared : TStringList;
  53. begin
  54. { try to create import entries from system dlls }
  55. if target_info.DllScanSupported and
  56. (not current_module.linkOtherSharedLibs.Empty) then
  57. begin
  58. { Init DLLScanner }
  59. if assigned(CDLLScanner[target_info.system]) then
  60. DLLScanner:=CDLLScanner[target_info.system].Create
  61. else
  62. internalerror(200104121);
  63. KeepShared:=TStringList.Create;
  64. { Walk all shared libs }
  65. While not current_module.linkOtherSharedLibs.Empty do
  66. begin
  67. S:=current_module.linkOtherSharedLibs.Getusemask(link_allways);
  68. if not DLLScanner.scan(s) then
  69. KeepShared.Concat(s);
  70. end;
  71. DLLscanner.Free;
  72. { Recreate import section }
  73. if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
  74. begin
  75. if assigned(asmlist[al_imports]) then
  76. asmlist[al_imports].clear
  77. else
  78. asmlist[al_imports]:=taasmoutput.Create;
  79. importlib.generatelib;
  80. end;
  81. { Readd the not processed files }
  82. while not KeepShared.Empty do
  83. begin
  84. s:=KeepShared.GetFirst;
  85. current_module.linkOtherSharedLibs.add(s,link_allways);
  86. end;
  87. KeepShared.Free;
  88. end;
  89. { Start and end of debuginfo, at least required for stabs
  90. to insert n_sourcefile lines }
  91. if (cs_debuginfo in aktmoduleswitches) or
  92. (cs_gdb_lineinfo in aktglobalswitches) then
  93. begin
  94. debuginfo.insertmodulestart(asmlist[al_debugstart]);
  95. debuginfo.insertmoduleend(asmlist[al_debugend]);
  96. end;
  97. { create the .s file and assemble it }
  98. GenerateAsm(false);
  99. { Also create a smartlinked version ? }
  100. if (cs_create_smart in aktmoduleswitches) and
  101. not(af_smartlink_sections in target_asm.flags) then
  102. begin
  103. { regenerate the importssection for win32 }
  104. if assigned(asmlist[al_imports]) and
  105. (target_info.system in [system_i386_win32,system_i386_wdosx, system_arm_wince,system_i386_wince]) then
  106. begin
  107. asmlist[al_imports].clear;
  108. importlib.generatesmartlib;
  109. end;
  110. GenerateAsm(true);
  111. if (af_needar in target_asm.flags) then
  112. Linker.MakeStaticLibrary;
  113. end;
  114. { resource files }
  115. CompileResourceFiles;
  116. end;
  117. procedure insertobjectfile;
  118. { Insert the used object file for this unit in the used list for this unit }
  119. begin
  120. current_module.linkunitofiles.add(current_module.objfilename^,link_static);
  121. current_module.flags:=current_module.flags or uf_static_linked;
  122. if (cs_create_smart in aktmoduleswitches) and
  123. not(af_smartlink_sections in target_asm.flags) then
  124. begin
  125. current_module.linkunitstaticlibs.add(current_module.staticlibfilename^,link_smart);
  126. current_module.flags:=current_module.flags or uf_smart_linked;
  127. end;
  128. end;
  129. procedure create_dwarf;
  130. begin
  131. asmlist[al_dwarf]:=taasmoutput.create;
  132. { Call frame information }
  133. if (tf_needs_dwarf_cfi in target_info.flags) and
  134. (af_supports_dwarf in target_asm.flags) then
  135. dwarfcfi.generate_code(asmlist[al_dwarf]);
  136. end;
  137. (*
  138. procedure insertsegment;
  139. var
  140. oldaktfilepos : tfileposinfo;
  141. {Note: Sections get names in macos only.}
  142. begin
  143. { Insert Ident of the compiler }
  144. if (not (cs_create_smart in aktmoduleswitches))
  145. {$ifndef EXTDEBUG}
  146. and (not current_module.is_unit)
  147. {$endif}
  148. then
  149. begin
  150. { align the first data }
  151. asmlist[al_globals].insert(Tai_align.Create(const_align(32)));
  152. asmlist[al_globals].insert(Tai_string.Create('FPC '+full_version_string+
  153. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname));
  154. end;
  155. { align code segment }
  156. asmlist[al_procedures].concat(Tai_align.create(aktalignment.procalign));
  157. { Insert start and end of sections }
  158. fixseg(asmlist[al_procedures],sec_code,'____seg_code');
  159. fixseg(asmlist[al_globals],sec_data,'____seg_data');
  160. fixseg(asmlist[al_const],sec_rodata,'____seg_rodata');
  161. // fixseg(asmlist[al_bss],sec_bss,'____seg_bss');
  162. fixseg(asmlist[al_threadvars],sec_bss,'____seg_tbss');
  163. { we should use .rdata section for these two no ?
  164. .rdata is a read only data section (PM) }
  165. fixseg(asmlist[al_rtti],sec_data,'____seg_rtti');
  166. fixseg(asmlist[al_typedconsts],sec_data,'____seg_consts');
  167. fixseg(asmlist[al_rotypedconsts],sec_rodata,'____seg_consts');
  168. fixseg(asmlist[al_picdata],sec_data,'____seg_al_picdata');
  169. if assigned(asmlist[aasmtai.al_resourcestrings]) then
  170. fixseg(asmlist[aasmtai.al_resourcestrings],sec_data,'____seg_resstrings');
  171. {$ifdef GDB}
  172. if assigned(asmlist[al_debugtypes]) then
  173. begin
  174. oldaktfilepos:=aktfilepos;
  175. aktfilepos.line:=0;
  176. asmlist[al_debugtypes].insert(Tai_symbol.Createname('gcc2_compiled',AT_DATA,0));
  177. asmlist[al_debugtypes].insert(Tai_symbol.Createname('fpc_compiled',AT_DATA,0));
  178. // fixseg(asmlist[al_debugtypes],sec_code,'____seg_debug');
  179. aktfilepos:=oldaktfilepos;
  180. end;
  181. {$endif GDB}
  182. end;
  183. *)
  184. {$ifndef segment_threadvars}
  185. procedure InsertThreadvarTablesTable;
  186. var
  187. hp : tused_unit;
  188. ltvTables : taasmoutput;
  189. count : longint;
  190. begin
  191. ltvTables:=TAAsmOutput.Create;
  192. count:=0;
  193. hp:=tused_unit(usedunits.first);
  194. while assigned(hp) do
  195. begin
  196. If (hp.u.flags and uf_threadvars)=uf_threadvars then
  197. begin
  198. ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',hp.u.globalsymtable,''),AT_DATA,0));
  199. inc(count);
  200. end;
  201. hp:=tused_unit(hp.next);
  202. end;
  203. { Add program threadvars, if any }
  204. If (current_module.flags and uf_threadvars)=uf_threadvars then
  205. begin
  206. ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',current_module.localsymtable,''),AT_DATA,0));
  207. inc(count);
  208. end;
  209. { Insert TableCount at start }
  210. ltvTables.insert(Tai_const.Create_32bit(count));
  211. { insert in data segment }
  212. maybe_new_object_file(asmlist[al_globals]);
  213. new_section(asmlist[al_globals],sec_data,'FPC_THREADVARTABLES',sizeof(aint));
  214. asmlist[al_globals].concat(Tai_symbol.Createname_global('FPC_THREADVARTABLES',AT_DATA,0));
  215. asmlist[al_globals].concatlist(ltvTables);
  216. asmlist[al_globals].concat(Tai_symbol_end.Createname('FPC_THREADVARTABLES'));
  217. ltvTables.free;
  218. end;
  219. procedure AddToThreadvarList(p:tnamedindexitem;arg:pointer);
  220. var
  221. ltvTable : taasmoutput;
  222. begin
  223. ltvTable:=taasmoutput(arg);
  224. if (tsym(p).typ=globalvarsym) and
  225. (vo_is_thread_var in tglobalvarsym(p).varoptions) then
  226. begin
  227. { address of threadvar }
  228. ltvTable.concat(tai_const.Createname(tglobalvarsym(p).mangledname,AT_DATA,0));
  229. { size of threadvar }
  230. ltvTable.concat(tai_const.create_32bit(tglobalvarsym(p).getsize));
  231. end;
  232. end;
  233. procedure InsertThreadvars;
  234. var
  235. s : string;
  236. ltvTable : TAAsmoutput;
  237. begin
  238. ltvTable:=TAAsmoutput.create;
  239. if assigned(current_module.globalsymtable) then
  240. current_module.globalsymtable.foreach_static(@AddToThreadvarList,ltvTable);
  241. current_module.localsymtable.foreach_static(@AddToThreadvarList,ltvTable);
  242. if ltvTable.first<>nil then
  243. begin
  244. s:=make_mangledname('THREADVARLIST',current_module.localsymtable,'');
  245. { end of the list marker }
  246. ltvTable.concat(tai_const.create_sym(nil));
  247. { add to datasegment }
  248. maybe_new_object_file(asmlist[al_globals]);
  249. new_section(asmlist[al_globals],sec_data,s,sizeof(aint));
  250. asmlist[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  251. asmlist[al_globals].concatlist(ltvTable);
  252. asmlist[al_globals].concat(Tai_symbol_end.Createname(s));
  253. current_module.flags:=current_module.flags or uf_threadvars;
  254. end;
  255. ltvTable.Free;
  256. end;
  257. {$endif}
  258. Procedure InsertResourceInfo;
  259. var
  260. hp : tused_unit;
  261. found : Boolean;
  262. I : Integer;
  263. ResourceInfo : taasmoutput;
  264. begin
  265. if target_res.id=res_elf then
  266. begin
  267. hp:=tused_unit(usedunits.first);
  268. found:=false;
  269. Found:=((current_module.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
  270. If not found then
  271. While Assigned(hp) and not Found do
  272. begin
  273. Found:=((hp.u.flags and uf_has_resourcefiles)=uf_has_resourcefiles);
  274. hp:=tused_unit(hp.next);
  275. end;
  276. ResourceInfo:=TAAsmOutput.Create;
  277. if found then
  278. begin
  279. { Valid pointer to resource information }
  280. ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESLOCATION',AT_DATA,0));
  281. ResourceInfo.concat(Tai_const.Createname('FPC_RESSYMBOL',AT_DATA,0));
  282. {$ifdef EXTERNALRESPTRS}
  283. current_module.linkotherofiles.add('resptrs.o',link_allways);
  284. {$else EXTERNALRESPTRS}
  285. new_section(ResourceInfo,sec_fpc,'resptrs',4);
  286. ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESSYMBOL',AT_DATA,0));
  287. For I:=1 to 32 do
  288. ResourceInfo.Concat(Tai_const.Create_32bit(0));
  289. {$endif EXTERNALRESPTRS}
  290. end
  291. else
  292. begin
  293. { Nil pointer to resource information }
  294. ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESLOCATION',AT_DATA,0));
  295. ResourceInfo.Concat(Tai_const.Create_32bit(0));
  296. end;
  297. maybe_new_object_file(asmlist[al_globals]);
  298. asmlist[al_globals].concatlist(ResourceInfo);
  299. ResourceInfo.free;
  300. end;
  301. end;
  302. Procedure InsertResourceTablesTable;
  303. var
  304. hp : tused_unit;
  305. ResourceStringTables : taasmoutput;
  306. count : longint;
  307. begin
  308. ResourceStringTables:=TAAsmOutput.Create;
  309. count:=0;
  310. hp:=tused_unit(usedunits.first);
  311. while assigned(hp) do
  312. begin
  313. If (hp.u.flags and uf_has_resources)=uf_has_resources then
  314. begin
  315. ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',hp.u.globalsymtable,''),AT_DATA,0));
  316. inc(count);
  317. end;
  318. hp:=tused_unit(hp.next);
  319. end;
  320. { Add program resources, if any }
  321. If resourcestrings.ResStrCount>0 then
  322. begin
  323. ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESOURCESTRINGLIST',current_module.localsymtable,''),AT_DATA,0));
  324. Inc(Count);
  325. end;
  326. { Insert TableCount at start }
  327. ResourceStringTables.insert(Tai_const.Create_32bit(count));
  328. { Add to data segment }
  329. maybe_new_object_file(asmlist[al_globals]);
  330. new_section(asmlist[al_globals],sec_data,'FPC_RESOURCESTRINGTABLES',sizeof(aint));
  331. asmlist[al_globals].concat(Tai_symbol.Createname_global('FPC_RESOURCESTRINGTABLES',AT_DATA,0));
  332. asmlist[al_globals].concatlist(ResourceStringTables);
  333. asmlist[al_globals].concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
  334. ResourceStringTables.free;
  335. end;
  336. procedure InsertInitFinalTable;
  337. var
  338. hp : tused_unit;
  339. unitinits : taasmoutput;
  340. count : longint;
  341. begin
  342. unitinits:=TAAsmOutput.Create;
  343. count:=0;
  344. hp:=tused_unit(usedunits.first);
  345. while assigned(hp) do
  346. begin
  347. { call the unit init code and make it external }
  348. if (hp.u.flags and (uf_init or uf_finalize))<>0 then
  349. begin
  350. if (hp.u.flags and uf_init)<>0 then
  351. unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',hp.u.globalsymtable,''),AT_FUNCTION,0))
  352. else
  353. unitinits.concat(Tai_const.Create_sym(nil));
  354. if (hp.u.flags and uf_finalize)<>0 then
  355. unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',hp.u.globalsymtable,''),AT_FUNCTION,0))
  356. else
  357. unitinits.concat(Tai_const.Create_sym(nil));
  358. inc(count);
  359. end;
  360. hp:=tused_unit(hp.next);
  361. end;
  362. { Insert initialization/finalization of the program }
  363. if (current_module.flags and (uf_init or uf_finalize))<>0 then
  364. begin
  365. if (current_module.flags and uf_init)<>0 then
  366. unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',current_module.localsymtable,''),AT_FUNCTION,0))
  367. else
  368. unitinits.concat(Tai_const.Create_sym(nil));
  369. if (current_module.flags and uf_finalize)<>0 then
  370. unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',current_module.localsymtable,''),AT_FUNCTION,0))
  371. else
  372. unitinits.concat(Tai_const.Create_sym(nil));
  373. inc(count);
  374. end;
  375. { Insert TableCount,InitCount at start }
  376. unitinits.insert(Tai_const.Create_32bit(0));
  377. unitinits.insert(Tai_const.Create_32bit(count));
  378. { Add to data segment }
  379. maybe_new_object_file(asmlist[al_globals]);
  380. new_section(asmlist[al_globals],sec_data,'INITFINAL',sizeof(aint));
  381. asmlist[al_globals].concat(Tai_symbol.Createname_global('INITFINAL',AT_DATA,0));
  382. asmlist[al_globals].concatlist(unitinits);
  383. asmlist[al_globals].concat(Tai_symbol_end.Createname('INITFINAL'));
  384. unitinits.free;
  385. end;
  386. procedure insertmemorysizes;
  387. begin
  388. { stacksize can be specified and is now simulated }
  389. maybe_new_object_file(asmlist[al_globals]);
  390. new_section(asmlist[al_globals],sec_data,'__stklen',4);
  391. asmlist[al_globals].concat(Tai_symbol.Createname_global('__stklen',AT_DATA,4));
  392. asmlist[al_globals].concat(Tai_const.Create_32bit(stacksize));
  393. { Initial heapsize }
  394. maybe_new_object_file(asmlist[al_globals]);
  395. new_section(asmlist[al_globals],sec_data,'__heapsize',4);
  396. asmlist[al_globals].concat(Tai_symbol.Createname_global('__heapsize',AT_DATA,4));
  397. asmlist[al_globals].concat(Tai_const.Create_32bit(heapsize));
  398. end;
  399. procedure AddUnit(const s:string);
  400. var
  401. hp : tppumodule;
  402. unitsym : tunitsym;
  403. begin
  404. { load unit }
  405. hp:=registerunit(current_module,s,'');
  406. hp.loadppu;
  407. hp.adddependency(current_module);
  408. { add to symtable stack }
  409. tsymtable(hp.globalsymtable).next:=symtablestack;
  410. symtablestack:=hp.globalsymtable;
  411. if (m_mac in aktmodeswitches) and assigned(hp.globalmacrosymtable) then
  412. begin
  413. tsymtable(hp.globalmacrosymtable).next:=macrosymtablestack;
  414. macrosymtablestack:=hp.globalmacrosymtable;
  415. end;
  416. { insert unitsym }
  417. unitsym:=tunitsym.create(s,hp.globalsymtable);
  418. inc(unitsym.refs);
  419. refsymtable.insert(unitsym);
  420. { add to used units }
  421. current_module.addusedunit(hp,false,unitsym);
  422. end;
  423. procedure maybeloadvariantsunit;
  424. var
  425. hp : tmodule;
  426. begin
  427. { Do we need the variants unit? Skip this
  428. for VarUtils unit for bootstrapping }
  429. if (current_module.flags and uf_uses_variants=0) or
  430. (current_module.modulename^='VARUTILS') then
  431. exit;
  432. { Variants unit already loaded? }
  433. hp:=tmodule(loaded_units.first);
  434. while assigned(hp) do
  435. begin
  436. if hp.modulename^='VARIANTS' then
  437. exit;
  438. hp:=tmodule(hp.next);
  439. end;
  440. { Variants unit is not loaded yet, load it now }
  441. Message(parser_w_implicit_uses_of_variants_unit);
  442. AddUnit('Variants');
  443. end;
  444. procedure loaddefaultunits;
  445. begin
  446. { are we compiling the system unit? }
  447. if (cs_compilesystem in aktmoduleswitches) then
  448. begin
  449. { create system defines }
  450. createconstdefs;
  451. { we don't need to reset anything, it's already done in parser.pas }
  452. exit;
  453. end;
  454. { insert the system unit, it is allways the first }
  455. symtablestack:=nil;
  456. macrosymtablestack:=initialmacrosymtable;
  457. AddUnit('System');
  458. SystemUnit:=TGlobalSymtable(Symtablestack);
  459. { read default constant definitions }
  460. make_ref:=false;
  461. readconstdefs;
  462. make_ref:=true;
  463. { Set the owner of errorsym and errortype to symtable to
  464. prevent crashes when accessing .owner }
  465. generrorsym.owner:=systemunit;
  466. generrortype.def.owner:=systemunit;
  467. { Units only required for main module }
  468. { load heaptrace before any other units especially objpas }
  469. if not(current_module.is_unit) then
  470. begin
  471. { Heaptrc unit }
  472. if (cs_gdb_heaptrc in aktglobalswitches) then
  473. AddUnit('HeapTrc');
  474. { Lineinfo unit }
  475. if (cs_gdb_lineinfo in aktglobalswitches) then
  476. AddUnit('LineInfo');
  477. { Lineinfo unit }
  478. if (cs_gdb_valgrind in aktglobalswitches) then
  479. AddUnit('CMem');
  480. {$ifdef cpufpemu}
  481. { Floating point emulation unit? }
  482. if (cs_fp_emulation in aktmoduleswitches) and not(target_info.system in system_wince) then
  483. AddUnit('SoftFpu');
  484. {$endif cpufpemu}
  485. end;
  486. { Objpas unit? }
  487. if m_objpas in aktmodeswitches then
  488. AddUnit('ObjPas');
  489. { Macpas unit? }
  490. if m_mac in aktmodeswitches then
  491. AddUnit('MacPas');
  492. { Profile unit? Needed for go32v2 only }
  493. if (cs_profile in aktmoduleswitches) and
  494. (target_info.system in [system_i386_go32v2,system_i386_watcom]) then
  495. AddUnit('Profile');
  496. if (cs_load_fpcylix_unit in aktglobalswitches) then
  497. AddUnit('FPCylix');
  498. { save default symtablestack }
  499. defaultsymtablestack:=symtablestack;
  500. defaultmacrosymtablestack:=macrosymtablestack;
  501. end;
  502. procedure loadautounits;
  503. var
  504. hs,s : string;
  505. begin
  506. hs:=autoloadunits;
  507. repeat
  508. s:=GetToken(hs,',');
  509. if s='' then
  510. break;
  511. AddUnit(s);
  512. until false;
  513. end;
  514. procedure loadunits;
  515. var
  516. s,sorg : stringid;
  517. fn : string;
  518. pu : tused_unit;
  519. hp2 : tmodule;
  520. hp3 : tsymtable;
  521. unitsym : tunitsym;
  522. top_of_macrosymtable : tsymtable;
  523. begin
  524. consume(_USES);
  525. {$ifdef DEBUG}
  526. test_symtablestack;
  527. {$endif DEBUG}
  528. repeat
  529. s:=pattern;
  530. sorg:=orgpattern;
  531. consume(_ID);
  532. { support "<unit> in '<file>'" construct, but not for tp7 }
  533. if not(m_tp7 in aktmodeswitches) then
  534. begin
  535. if try_to_consume(_OP_IN) then
  536. fn:=FixFileName(get_stringconst)
  537. else
  538. fn:='';
  539. end;
  540. { Give a warning if objpas is loaded }
  541. if s='OBJPAS' then
  542. Message(parser_w_no_objpas_use_mode);
  543. { Using the unit itself is not possible }
  544. if (s<>current_module.modulename^) then
  545. begin
  546. { check if the unit is already used }
  547. hp2:=nil;
  548. pu:=tused_unit(current_module.used_units.first);
  549. while assigned(pu) do
  550. begin
  551. if (pu.u.modulename^=s) then
  552. begin
  553. hp2:=pu.u;
  554. break;
  555. end;
  556. pu:=tused_unit(pu.next);
  557. end;
  558. if not assigned(hp2) then
  559. hp2:=registerunit(current_module,sorg,fn)
  560. else
  561. Message1(sym_e_duplicate_id,s);
  562. { Create unitsym, we need to use the name as specified, we
  563. can not use the modulename because that can be different
  564. when -Un is used }
  565. unitsym:=tunitsym.create(sorg,nil);
  566. refsymtable.insert(unitsym);
  567. { the current module uses the unit hp2 }
  568. current_module.addusedunit(hp2,true,unitsym);
  569. end
  570. else
  571. Message1(sym_e_duplicate_id,s);
  572. if token=_COMMA then
  573. begin
  574. pattern:='';
  575. consume(_COMMA);
  576. end
  577. else
  578. break;
  579. until false;
  580. { Load the units }
  581. top_of_macrosymtable:= macrosymtablestack;
  582. pu:=tused_unit(current_module.used_units.first);
  583. while assigned(pu) do
  584. begin
  585. { Only load the units that are in the current
  586. (interface/implementation) uses clause }
  587. if pu.in_uses and
  588. (pu.in_interface=current_module.in_interface) then
  589. begin
  590. tppumodule(pu.u).loadppu;
  591. { is our module compiled? then we can stop }
  592. if current_module.state=ms_compiled then
  593. exit;
  594. { add this unit to the dependencies }
  595. pu.u.adddependency(current_module);
  596. { save crc values }
  597. pu.checksum:=pu.u.crc;
  598. pu.interface_checksum:=pu.u.interface_crc;
  599. { connect unitsym to the globalsymtable of the unit }
  600. pu.unitsym.unitsymtable:=pu.u.globalsymtable;
  601. end;
  602. pu:=tused_unit(pu.next);
  603. end;
  604. { set the symtable to systemunit so it gets reorderd correctly,
  605. then insert the units in the symtablestack }
  606. pu:=tused_unit(current_module.used_units.first);
  607. symtablestack:=defaultsymtablestack;
  608. macrosymtablestack:=defaultmacrosymtablestack;
  609. while assigned(pu) do
  610. begin
  611. if pu.in_uses then
  612. begin
  613. { Reinsert in symtablestack }
  614. hp3:=symtablestack;
  615. while assigned(hp3) do
  616. begin
  617. { insert units only once ! }
  618. if pu.u.globalsymtable=hp3 then
  619. break;
  620. hp3:=hp3.next;
  621. { unit isn't inserted }
  622. if hp3=nil then
  623. begin
  624. tsymtable(pu.u.globalsymtable).next:=symtablestack;
  625. symtablestack:=tsymtable(pu.u.globalsymtable);
  626. if (m_mac in aktmodeswitches) and assigned(pu.u.globalmacrosymtable) then
  627. begin
  628. tsymtable(pu.u.globalmacrosymtable).next:=macrosymtablestack;
  629. macrosymtablestack:=tsymtable(pu.u.globalmacrosymtable);
  630. end;
  631. {$ifdef DEBUG}
  632. test_symtablestack;
  633. {$endif DEBUG}
  634. end;
  635. end;
  636. end;
  637. pu:=tused_unit(pu.next);
  638. end;
  639. if assigned (current_module.globalmacrosymtable) then
  640. top_of_macrosymtable.next.next:= macrosymtablestack
  641. else
  642. top_of_macrosymtable.next:= macrosymtablestack;
  643. macrosymtablestack:= top_of_macrosymtable;
  644. consume(_SEMICOLON);
  645. end;
  646. {$IfDef GDB}
  647. procedure write_gdb_info;
  648. procedure reset_unit_type_info;
  649. var
  650. hp : tmodule;
  651. begin
  652. hp:=tmodule(loaded_units.first);
  653. while assigned(hp) do
  654. begin
  655. hp.is_stab_written:=false;
  656. hp:=tmodule(hp.next);
  657. end;
  658. end;
  659. procedure write_used_unit_type_info(hp:tmodule);
  660. var
  661. pu : tused_unit;
  662. begin
  663. pu:=tused_unit(hp.used_units.first);
  664. while assigned(pu) do
  665. begin
  666. if not pu.u.is_stab_written then
  667. begin
  668. { prevent infinte loop for circular dependencies }
  669. pu.u.is_stab_written:=true;
  670. { write type info from used units, use a depth first
  671. strategy to reduce the recursion in writing all
  672. dependent stabs }
  673. write_used_unit_type_info(pu.u);
  674. if assigned(pu.u.globalsymtable) then
  675. tglobalsymtable(pu.u.globalsymtable).concattypestabto(asmlist[al_debugtypes]);
  676. end;
  677. pu:=tused_unit(pu.next);
  678. end;
  679. end;
  680. var
  681. temptypestabs : taasmoutput;
  682. storefilepos : tfileposinfo;
  683. st : tsymtable;
  684. begin
  685. if not (cs_debuginfo in aktmoduleswitches) then
  686. exit;
  687. storefilepos:=aktfilepos;
  688. aktfilepos:=current_module.mainfilepos;
  689. { include symbol that will be referenced from the program to be sure to
  690. include this debuginfo .o file }
  691. if current_module.is_unit then
  692. begin
  693. current_module.flags:=current_module.flags or uf_has_debuginfo;
  694. st:=current_module.globalsymtable;
  695. end
  696. else
  697. st:=current_module.localsymtable;
  698. new_section(asmlist[al_debugtypes],sec_data,lower(st.name^),0);
  699. asmlist[al_debugtypes].concat(tai_symbol.Createname_global(make_mangledname('DEBUGINFO',st,''),AT_DATA,0));
  700. { first write all global/local symbols again to a temp list. This will flag
  701. all required tdefs. After that the temp list can be removed since the debuginfo is already
  702. written to the stabs when the variables/consts were written }
  703. {$warning Hack to get all needed types}
  704. temptypestabs:=taasmoutput.create;
  705. if assigned(current_module.globalsymtable) then
  706. tglobalsymtable(current_module.globalsymtable).concatstabto(temptypestabs);
  707. if assigned(current_module.localsymtable) then
  708. tstaticsymtable(current_module.localsymtable).concatstabto(temptypestabs);
  709. temptypestabs.free;
  710. { reset unit type info flag }
  711. reset_unit_type_info;
  712. { write used types from the used units }
  713. write_used_unit_type_info(current_module);
  714. { last write the types from this unit }
  715. if assigned(current_module.globalsymtable) then
  716. tglobalsymtable(current_module.globalsymtable).concattypestabto(asmlist[al_debugtypes]);
  717. if assigned(current_module.localsymtable) then
  718. tstaticsymtable(current_module.localsymtable).concattypestabto(asmlist[al_debugtypes]);
  719. { include files }
  720. if (cs_gdb_dbx in aktglobalswitches) then
  721. begin
  722. asmlist[al_debugtypes].concat(tai_comment.Create(strpnew('EINCL of global '+
  723. tglobalsymtable(current_module.globalsymtable).name^+' has index '+
  724. tostr(tglobalsymtable(current_module.globalsymtable).moduleid))));
  725. asmlist[al_debugtypes].concat(Tai_stab.create(stab_stabs,strpnew('"'+
  726. tglobalsymtable(current_module.globalsymtable).name^+'",'+
  727. tostr(N_EINCL)+',0,0,0')));
  728. tglobalsymtable(current_module.globalsymtable).dbx_count_ok:={true}false;
  729. dbx_counter:=tglobalsymtable(current_module.globalsymtable).prev_dbx_counter;
  730. do_count_dbx:=false;
  731. end;
  732. aktfilepos:=storefilepos;
  733. end;
  734. {$EndIf GDB}
  735. procedure reset_all_defs;
  736. procedure reset_used_unit_defs(hp:tmodule);
  737. var
  738. pu : tused_unit;
  739. begin
  740. pu:=tused_unit(hp.used_units.first);
  741. while assigned(pu) do
  742. begin
  743. if not pu.u.is_reset then
  744. begin
  745. { prevent infinte loop for circular dependencies }
  746. pu.u.is_reset:=true;
  747. if assigned(pu.u.globalsymtable) then
  748. begin
  749. tglobalsymtable(pu.u.globalsymtable).reset_all_defs;
  750. reset_used_unit_defs(pu.u);
  751. end;
  752. end;
  753. pu:=tused_unit(pu.next);
  754. end;
  755. end;
  756. var
  757. hp2 : tmodule;
  758. begin
  759. hp2:=tmodule(loaded_units.first);
  760. while assigned(hp2) do
  761. begin
  762. hp2.is_reset:=false;
  763. hp2:=tmodule(hp2.next);
  764. end;
  765. reset_used_unit_defs(current_module);
  766. end;
  767. procedure free_localsymtables(st:tsymtable);
  768. var
  769. def : tstoreddef;
  770. pd : tprocdef;
  771. begin
  772. def:=tstoreddef(st.defindex.first);
  773. while assigned(def) do
  774. begin
  775. if def.deftype=procdef then
  776. begin
  777. pd:=tprocdef(def);
  778. if assigned(pd.localst) and
  779. (pd.localst.symtabletype<>staticsymtable) and
  780. not((po_inline in pd.procoptions) or
  781. ((current_module.flags and uf_local_browser)<>0)) then
  782. begin
  783. free_localsymtables(pd.localst);
  784. pd.localst.free;
  785. pd.localst:=nil;
  786. end;
  787. end;
  788. def:=tstoreddef(def.indexnext);
  789. end;
  790. end;
  791. procedure parse_implementation_uses;
  792. begin
  793. if token=_USES then
  794. begin
  795. loadunits;
  796. {$ifdef DEBUG}
  797. test_symtablestack;
  798. {$endif DEBUG}
  799. end;
  800. end;
  801. procedure setupglobalswitches;
  802. begin
  803. { can't have local browser when no global browser }
  804. if (cs_local_browser in aktmoduleswitches) and
  805. not(cs_browser in aktmoduleswitches) then
  806. exclude(aktmoduleswitches,cs_local_browser);
  807. if (cs_create_pic in aktmoduleswitches) then
  808. def_system_macro('FPC_PIC');
  809. end;
  810. function create_main_proc(const name:string;potype:tproctypeoption;st:tsymtable):tprocdef;
  811. var
  812. stt : tsymtable;
  813. ps : tprocsym;
  814. pd : tprocdef;
  815. begin
  816. { there should be no current_procinfo available }
  817. if assigned(current_procinfo) then
  818. internalerror(200304275);
  819. {Generate a procsym for main}
  820. make_ref:=false;
  821. { try to insert in in static symtable ! }
  822. stt:=symtablestack;
  823. symtablestack:=st;
  824. { generate procsym }
  825. ps:=tprocsym.create('$'+name);
  826. { main are allways used }
  827. inc(ps.refs);
  828. symtablestack.insert(ps);
  829. pd:=tprocdef.create(main_program_level);
  830. include(pd.procoptions,po_global);
  831. pd.procsym:=ps;
  832. ps.addprocdef(pd);
  833. { restore symtable }
  834. make_ref:=true;
  835. symtablestack:=stt;
  836. { set procdef options }
  837. pd.proctypeoption:=potype;
  838. pd.proccalloption:=pocall_default;
  839. pd.forwarddef:=false;
  840. pd.setmangledname(target_info.cprefix+name);
  841. pd.aliasnames.insert(pd.mangledname);
  842. handle_calling_convention(pd);
  843. { We don't need is a local symtable. Change it into the static
  844. symtable }
  845. pd.localst.free;
  846. pd.localst:=st;
  847. { set procinfo and current_procinfo.procdef }
  848. current_procinfo:=cprocinfo.create(nil);
  849. current_module.procinfo:=current_procinfo;
  850. current_procinfo.procdef:=pd;
  851. { return procdef }
  852. create_main_proc:=pd;
  853. { main proc does always a call e.g. to init system unit }
  854. include(current_procinfo.flags,pi_do_call);
  855. end;
  856. procedure release_main_proc(pd:tprocdef);
  857. begin
  858. { this is a main proc, so there should be no parent }
  859. if not(assigned(current_procinfo)) or
  860. assigned(current_procinfo.parent) or
  861. not(current_procinfo.procdef=pd) then
  862. internalerror(200304276);
  863. { remove procinfo }
  864. current_module.procinfo:=nil;
  865. current_procinfo.free;
  866. current_procinfo:=nil;
  867. { remove localst as it was replaced by staticsymtable }
  868. pd.localst:=nil;
  869. end;
  870. procedure gen_implicit_initfinal(flag:word;st:tsymtable);
  871. var
  872. pd : tprocdef;
  873. begin
  874. { update module flags }
  875. current_module.flags:=current_module.flags or flag;
  876. { create procdef }
  877. case flag of
  878. uf_init :
  879. begin
  880. pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'init_implicit'),potype_unitinit,st);
  881. pd.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
  882. end;
  883. uf_finalize :
  884. begin
  885. pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize_implicit'),potype_unitfinalize,st);
  886. pd.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
  887. end;
  888. else
  889. internalerror(200304253);
  890. end;
  891. tcgprocinfo(current_procinfo).code:=cnothingnode.create;
  892. tcgprocinfo(current_procinfo).generate_code;
  893. release_main_proc(pd);
  894. end;
  895. procedure delete_duplicate_macros(p:TNamedIndexItem; arg:pointer);
  896. var
  897. hp: tsymentry;
  898. begin
  899. hp:= current_module.localmacrosymtable.search(p.name);
  900. if assigned(hp) then
  901. current_module.localmacrosymtable.delete(hp);
  902. end;
  903. procedure proc_unit;
  904. function is_assembler_generated:boolean;
  905. begin
  906. is_assembler_generated:=(Errorcount=0) and
  907. not(
  908. asmlist[al_procedures].empty and
  909. asmlist[al_globals].empty and
  910. // asmlist[al_bss].empty and
  911. asmlist[al_threadvars].empty and
  912. asmlist[al_rtti].empty and
  913. ((asmlist[al_imports]=nil) or asmlist[al_imports].empty) and
  914. ((asmlist[al_resources]=nil) or asmlist[al_resources].empty) and
  915. ((asmlist[aasmtai.al_resourcestrings]=nil) or asmlist[aasmtai.al_resourcestrings].empty)
  916. );
  917. end;
  918. var
  919. main_file: tinputfile;
  920. st : tsymtable;
  921. unitst : tglobalsymtable;
  922. {$ifdef EXTDEBUG}
  923. store_crc,
  924. {$endif EXTDEBUG}
  925. store_interface_crc : cardinal;
  926. s1,s2 : ^string; {Saves stack space}
  927. force_init_final : boolean;
  928. pd : tprocdef;
  929. unitname8 : string[8];
  930. has_impl,ag: boolean;
  931. begin
  932. if m_mac in aktmodeswitches then
  933. begin
  934. ConsolidateMode;
  935. current_module.mode_switch_allowed:= false;
  936. end;
  937. consume(_UNIT);
  938. if compile_level=1 then
  939. Status.IsExe:=false;
  940. if token=_ID then
  941. begin
  942. { create filenames and unit name }
  943. main_file := current_scanner.inputfile;
  944. while assigned(main_file.next) do
  945. main_file := main_file.next;
  946. new(s1);
  947. s1^:=current_module.modulename^;
  948. current_module.SetFileName(main_file.path^+main_file.name^,true);
  949. current_module.SetModuleName(orgpattern);
  950. { check for system unit }
  951. new(s2);
  952. s2^:=upper(SplitName(main_file.name^));
  953. unitname8:=copy(current_module.modulename^,1,8);
  954. if (cs_check_unit_name in aktglobalswitches) and
  955. (
  956. not(
  957. (current_module.modulename^=s2^) or
  958. (
  959. (length(current_module.modulename^)>8) and
  960. (unitname8=s2^)
  961. )
  962. )
  963. or
  964. (
  965. (length(s1^)>8) and
  966. (s1^<>current_module.modulename^)
  967. )
  968. ) then
  969. Message1(unit_e_illegal_unit_name,current_module.realmodulename^);
  970. if (current_module.modulename^='SYSTEM') then
  971. include(aktmoduleswitches,cs_compilesystem);
  972. dispose(s2);
  973. dispose(s1);
  974. end;
  975. consume(_ID);
  976. consume(_SEMICOLON);
  977. consume(_INTERFACE);
  978. { global switches are read, so further changes aren't allowed }
  979. current_module.in_global:=false;
  980. { handle the global switches }
  981. ConsolidateMode;
  982. setupglobalswitches;
  983. message1(unit_u_loading_interface_units,current_module.modulename^);
  984. { update status }
  985. status.currentmodule:=current_module.realmodulename^;
  986. { maybe turn off m_objpas if we are compiling objpas }
  987. if (current_module.modulename^='OBJPAS') then
  988. exclude(aktmodeswitches,m_objpas);
  989. { maybe turn off m_mac if we are compiling macpas }
  990. if (current_module.modulename^='MACPAS') then
  991. exclude(aktmodeswitches,m_mac);
  992. parse_only:=true;
  993. { generate now the global symboltable }
  994. st:=tglobalsymtable.create(current_module.modulename^,current_module.moduleid);
  995. refsymtable:=st;
  996. unitst:=tglobalsymtable(st);
  997. { define first as local to overcome dependency conflicts }
  998. current_module.localsymtable:=st;
  999. { the unit name must be usable as a unit specifier }
  1000. { inside the unit itself (PM) }
  1001. { this also forbids to have another symbol }
  1002. { with the same name as the unit }
  1003. refsymtable.insert(tunitsym.create(current_module.realmodulename^,unitst));
  1004. macrosymtablestack:= initialmacrosymtable;
  1005. { load default units, like the system unit }
  1006. loaddefaultunits;
  1007. current_module.localmacrosymtable.next:=macrosymtablestack;
  1008. if assigned(current_module.globalmacrosymtable) then
  1009. begin
  1010. current_module.globalmacrosymtable.next:= current_module.localmacrosymtable;
  1011. macrosymtablestack:=current_module.globalmacrosymtable;
  1012. end
  1013. else
  1014. macrosymtablestack:=current_module.localmacrosymtable;
  1015. { reset }
  1016. make_ref:=true;
  1017. { insert qualifier for the system unit (allows system.writeln) }
  1018. if not(cs_compilesystem in aktmoduleswitches) then
  1019. begin
  1020. if token=_USES then
  1021. begin
  1022. loadunits;
  1023. { has it been compiled at a higher level ?}
  1024. if current_module.state=ms_compiled then
  1025. exit;
  1026. end;
  1027. { ... but insert the symbol table later }
  1028. st.next:=symtablestack;
  1029. symtablestack:=st;
  1030. end
  1031. else
  1032. { while compiling a system unit, some types are directly inserted }
  1033. begin
  1034. st.next:=symtablestack;
  1035. symtablestack:=st;
  1036. insert_intern_types(st);
  1037. end;
  1038. { now we know the place to insert the constants }
  1039. constsymtable:=symtablestack;
  1040. { move the global symtab from the temporary local to global }
  1041. current_module.globalsymtable:=current_module.localsymtable;
  1042. current_module.localsymtable:=nil;
  1043. reset_all_defs;
  1044. { number all units, so we know if a unit is used by this unit or
  1045. needs to be added implicitly }
  1046. current_module.updatemaps;
  1047. { ... parse the declarations }
  1048. Message1(parser_u_parsing_interface,current_module.realmodulename^);
  1049. read_interface_declarations;
  1050. { leave when we got an error }
  1051. if (Errorcount>0) and not status.skip_error then
  1052. begin
  1053. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1054. status.skip_error:=true;
  1055. exit;
  1056. end;
  1057. { Our interface is compiled, generate CRC and switch to implementation }
  1058. if not(cs_compilesystem in aktmoduleswitches) and
  1059. (Errorcount=0) then
  1060. tppumodule(current_module).getppucrc;
  1061. current_module.in_interface:=false;
  1062. current_module.interface_compiled:=true;
  1063. { First reload all units depending on our interface, we need to do this
  1064. in the implementation part to prevent errorneous circular references }
  1065. reload_flagged_units;
  1066. { Parse the implementation section }
  1067. if (m_mac in aktmodeswitches) and try_to_consume(_END) then
  1068. has_impl:= false
  1069. else
  1070. has_impl:= true;
  1071. parse_only:=false;
  1072. { generates static symbol table }
  1073. st:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
  1074. current_module.localsymtable:=st;
  1075. { Swap the positions of the local and global macro sym table}
  1076. if assigned(current_module.globalmacrosymtable) then
  1077. begin
  1078. macrosymtablestack:=current_module.localmacrosymtable;
  1079. current_module.globalmacrosymtable.next:= current_module.localmacrosymtable.next;
  1080. current_module.localmacrosymtable.next:=current_module.globalmacrosymtable;
  1081. current_module.globalmacrosymtable.foreach_static(@delete_duplicate_macros, nil);
  1082. end;
  1083. { remove the globalsymtable from the symtable stack }
  1084. { to reinsert it after loading the implementation units }
  1085. symtablestack:=unitst.next;
  1086. { we don't want implementation units symbols in unitsymtable !! PM }
  1087. refsymtable:=st;
  1088. if has_impl then
  1089. begin
  1090. consume(_IMPLEMENTATION);
  1091. Message1(unit_u_loading_implementation_units,current_module.modulename^);
  1092. { Read the implementation units }
  1093. parse_implementation_uses;
  1094. end;
  1095. if current_module.state=ms_compiled then
  1096. exit;
  1097. { reset ranges/stabs in exported definitions }
  1098. reset_all_defs;
  1099. { All units are read, now give them a number }
  1100. current_module.updatemaps;
  1101. { now we can change refsymtable }
  1102. refsymtable:=st;
  1103. { but reinsert the global symtable as lasts }
  1104. unitst.next:=symtablestack;
  1105. symtablestack:=unitst;
  1106. {$ifdef DEBUG}
  1107. test_symtablestack;
  1108. {$endif DEBUG}
  1109. constsymtable:=symtablestack;
  1110. if has_impl then
  1111. begin
  1112. Message1(parser_u_parsing_implementation,current_module.modulename^);
  1113. if current_module.in_interface then
  1114. internalerror(200212285);
  1115. { Compile the unit }
  1116. pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'init'),potype_unitinit,st);
  1117. pd.aliasnames.insert(make_mangledname('INIT$',current_module.localsymtable,''));
  1118. tcgprocinfo(current_procinfo).parse_body;
  1119. tcgprocinfo(current_procinfo).generate_code;
  1120. tcgprocinfo(current_procinfo).resetprocdef;
  1121. { save file pos for debuginfo }
  1122. current_module.mainfilepos:=current_procinfo.entrypos;
  1123. release_main_proc(pd);
  1124. end;
  1125. { if the unit contains ansi/widestrings, initialization and
  1126. finalization code must be forced }
  1127. force_init_final:=tglobalsymtable(current_module.globalsymtable).needs_init_final or
  1128. tstaticsymtable(current_module.localsymtable).needs_init_final;
  1129. { should we force unit initialization? }
  1130. { this is a hack, but how can it be done better ? }
  1131. if force_init_final and ((current_module.flags and uf_init)=0) then
  1132. gen_implicit_initfinal(uf_init,st);
  1133. { finalize? }
  1134. if has_impl and (token=_FINALIZATION) then
  1135. begin
  1136. { set module options }
  1137. current_module.flags:=current_module.flags or uf_finalize;
  1138. { Compile the finalize }
  1139. pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,st);
  1140. pd.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
  1141. tcgprocinfo(current_procinfo).parse_body;
  1142. tcgprocinfo(current_procinfo).generate_code;
  1143. tcgprocinfo(current_procinfo).resetprocdef;
  1144. release_main_proc(pd);
  1145. end
  1146. else if force_init_final then
  1147. gen_implicit_initfinal(uf_finalize,st);
  1148. { the last char should always be a point }
  1149. consume(_POINT);
  1150. { Generate resoucestrings }
  1151. If resourcestrings.ResStrCount>0 then
  1152. begin
  1153. resourcestrings.CreateResourceStringList;
  1154. current_module.flags:=current_module.flags or uf_has_resources;
  1155. { only write if no errors found }
  1156. if (Errorcount=0) then
  1157. resourcestrings.WriteResourceFile(ForceExtension(current_module.ppufilename^,'.rst'));
  1158. end;
  1159. if (Errorcount=0) then
  1160. begin
  1161. { tests, if all (interface) forwards are resolved }
  1162. tstoredsymtable(symtablestack).check_forwards;
  1163. { check if all private fields are used }
  1164. tstoredsymtable(symtablestack).allprivatesused;
  1165. { remove cross unit overloads }
  1166. tstoredsymtable(symtablestack).unchain_overloaded;
  1167. { test static symtable }
  1168. tstoredsymtable(st).allsymbolsused;
  1169. tstoredsymtable(st).allprivatesused;
  1170. tstoredsymtable(st).check_forwards;
  1171. tstoredsymtable(st).checklabels;
  1172. tstoredsymtable(st).unchain_overloaded;
  1173. { used units }
  1174. current_module.allunitsused;
  1175. end;
  1176. { leave when we got an error }
  1177. if (Errorcount>0) and not status.skip_error then
  1178. begin
  1179. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1180. status.skip_error:=true;
  1181. exit;
  1182. end;
  1183. { do we need to add the variants unit? }
  1184. maybeloadvariantsunit;
  1185. { generate debuginfo }
  1186. {$ifdef GDB}
  1187. write_gdb_info;
  1188. {$endif GDB}
  1189. { generate wrappers for interfaces }
  1190. gen_intf_wrappers(asmlist[al_procedures],current_module.globalsymtable);
  1191. gen_intf_wrappers(asmlist[al_procedures],current_module.localsymtable);
  1192. { generate a list of threadvars }
  1193. {$ifndef segment_threadvars}
  1194. InsertThreadvars;
  1195. {$endif}
  1196. { generate imports }
  1197. if current_module.uses_imports then
  1198. importlib.generatelib;
  1199. { insert own objectfile, or say that it's in a library
  1200. (no check for an .o when loading) }
  1201. ag:=is_assembler_generated;
  1202. if ag then
  1203. insertobjectfile
  1204. else
  1205. begin
  1206. current_module.flags:=current_module.flags or uf_no_link;
  1207. current_module.flags:=current_module.flags and not uf_has_debuginfo;
  1208. end;
  1209. if cs_local_browser in aktmoduleswitches then
  1210. current_module.localsymtable:=refsymtable;
  1211. if ag then
  1212. begin
  1213. { create dwarf debuginfo }
  1214. create_dwarf;
  1215. { finish asmlist by adding segment starts }
  1216. // insertsegment;
  1217. { assemble }
  1218. create_objectfile;
  1219. end;
  1220. { Write out the ppufile after the object file has been created }
  1221. store_interface_crc:=current_module.interface_crc;
  1222. {$ifdef EXTDEBUG}
  1223. store_crc:=current_module.crc;
  1224. {$endif EXTDEBUG}
  1225. if (Errorcount=0) then
  1226. tppumodule(current_module).writeppu;
  1227. if not(cs_compilesystem in aktmoduleswitches) then
  1228. if store_interface_crc<>current_module.interface_crc then
  1229. Message1(unit_u_interface_crc_changed,current_module.ppufilename^);
  1230. {$ifdef EXTDEBUG}
  1231. if not(cs_compilesystem in aktmoduleswitches) then
  1232. if (store_crc<>current_module.crc) and simplify_ppu then
  1233. Message1(unit_u_implementation_crc_changed,current_module.ppufilename^);
  1234. {$endif EXTDEBUG}
  1235. { release all overload references and local symtables that
  1236. are not needed anymore }
  1237. tstoredsymtable(current_module.localsymtable).unchain_overloaded;
  1238. tstoredsymtable(current_module.globalsymtable).unchain_overloaded;
  1239. free_localsymtables(current_module.globalsymtable);
  1240. free_localsymtables(current_module.localsymtable);
  1241. { remove static symtable (=refsymtable) here to save some mem, possible references
  1242. (like procsym overloads) should already have been freed above }
  1243. if not (cs_local_browser in aktmoduleswitches) then
  1244. begin
  1245. st.free;
  1246. current_module.localsymtable:=nil;
  1247. end;
  1248. { leave when we got an error }
  1249. if (Errorcount>0) and not status.skip_error then
  1250. begin
  1251. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1252. status.skip_error:=true;
  1253. exit;
  1254. end;
  1255. Message1(unit_u_finished_compiling,current_module.modulename^);
  1256. end;
  1257. procedure proc_program(islibrary : boolean);
  1258. var
  1259. main_file : tinputfile;
  1260. st : tsymtable;
  1261. hp,hp2 : tmodule;
  1262. pd : tprocdef;
  1263. begin
  1264. DLLsource:=islibrary;
  1265. Status.IsLibrary:=IsLibrary;
  1266. Status.IsExe:=true;
  1267. parse_only:=false;
  1268. { DLL defaults to create reloc info }
  1269. if islibrary then
  1270. begin
  1271. if not RelocSectionSetExplicitly then
  1272. RelocSection:=true;
  1273. end;
  1274. { relocation works only without stabs under win32 !! PM }
  1275. { internal assembler uses rva for stabs info
  1276. so it should work with relocated DLLs }
  1277. if RelocSection and
  1278. (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1279. (target_info.assem<>as_i386_pecoff) then
  1280. begin
  1281. include(aktglobalswitches,cs_link_strip);
  1282. { Warning stabs info does not work with reloc section !! }
  1283. if cs_debuginfo in aktmoduleswitches then
  1284. begin
  1285. Message1(parser_w_parser_reloc_no_debug,current_module.mainsource^);
  1286. Message(parser_w_parser_win32_debug_needs_WN);
  1287. exclude(aktmoduleswitches,cs_debuginfo);
  1288. end;
  1289. end;
  1290. { get correct output names }
  1291. main_file := current_scanner.inputfile;
  1292. while assigned(main_file.next) do
  1293. main_file := main_file.next;
  1294. current_module.SetFileName(main_file.path^+main_file.name^,true);
  1295. if islibrary then
  1296. begin
  1297. consume(_LIBRARY);
  1298. stringdispose(current_module.modulename);
  1299. stringdispose(current_module.realmodulename);
  1300. current_module.modulename:=stringdup(pattern);
  1301. current_module.realmodulename:=stringdup(orgpattern);
  1302. current_module.islibrary:=true;
  1303. exportlib.preparelib(orgpattern);
  1304. if tf_library_needs_pic in target_info.flags then
  1305. include(aktmoduleswitches,cs_create_pic);
  1306. consume(_ID);
  1307. consume(_SEMICOLON);
  1308. end
  1309. else
  1310. { is there an program head ? }
  1311. if token=_PROGRAM then
  1312. begin
  1313. consume(_PROGRAM);
  1314. stringdispose(current_module.modulename);
  1315. stringdispose(current_module.realmodulename);
  1316. current_module.modulename:=stringdup(pattern);
  1317. current_module.realmodulename:=stringdup(orgpattern);
  1318. if (target_info.system in [system_i386_WIN32,system_i386_wdosx]) then
  1319. exportlib.preparelib(orgpattern);
  1320. consume(_ID);
  1321. if token=_LKLAMMER then
  1322. begin
  1323. consume(_LKLAMMER);
  1324. repeat
  1325. consume(_ID);
  1326. until not try_to_consume(_COMMA);
  1327. consume(_RKLAMMER);
  1328. end;
  1329. consume(_SEMICOLON);
  1330. end
  1331. else if (target_info.system in [system_i386_WIN32,system_i386_wdosx]) then
  1332. exportlib.preparelib(current_module.realmodulename^);
  1333. { global switches are read, so further changes aren't allowed }
  1334. current_module.in_global:=false;
  1335. { setup things using the switches }
  1336. ConsolidateMode;
  1337. setupglobalswitches;
  1338. { set implementation flag }
  1339. current_module.in_interface:=false;
  1340. current_module.interface_compiled:=true;
  1341. { insert after the unit symbol tables the static symbol table }
  1342. { of the program }
  1343. st:=tstaticsymtable.create(current_module.modulename^,current_module.moduleid);
  1344. current_module.localsymtable:=st;
  1345. refsymtable:=st;
  1346. macrosymtablestack:= nil;
  1347. { load standard units (system,objpas,profile unit) }
  1348. loaddefaultunits;
  1349. current_module.localmacrosymtable.next:=macrosymtablestack;
  1350. macrosymtablestack:=current_module.localmacrosymtable;
  1351. { Load units provided on the command line }
  1352. loadautounits;
  1353. {Load the units used by the program we compile.}
  1354. if token=_USES then
  1355. loadunits;
  1356. { reset ranges/stabs in exported definitions }
  1357. reset_all_defs;
  1358. { All units are read, now give them a number }
  1359. current_module.updatemaps;
  1360. {Insert the name of the main program into the symbol table.}
  1361. if current_module.realmodulename^<>'' then
  1362. st.insert(tunitsym.create(current_module.realmodulename^,st));
  1363. { ...is also constsymtable, this is the symtable where }
  1364. { the elements of enumeration types are inserted }
  1365. constsymtable:=st;
  1366. Message1(parser_u_parsing_implementation,current_module.mainsource^);
  1367. { The program intialization needs an alias, so it can be called
  1368. from the bootstrap code.}
  1369. if islibrary then
  1370. begin
  1371. pd:=create_main_proc(make_mangledname('',current_module.localsymtable,mainaliasname),potype_proginit,st);
  1372. { Win32 startup code needs a single name }
  1373. // if (target_info.system in [system_i386_win32,system_i386_wdosx]) then
  1374. pd.aliasnames.insert('PASCALMAIN');
  1375. end
  1376. else if (target_info.system = system_i386_netware) or
  1377. (target_info.system = system_i386_netwlibc) then
  1378. begin
  1379. pd:=create_main_proc('PASCALMAIN',potype_proginit,st); { main is need by the netware rtl }
  1380. end
  1381. else
  1382. begin
  1383. pd:=create_main_proc(mainaliasname,potype_proginit,st);
  1384. pd.aliasnames.insert('PASCALMAIN');
  1385. end;
  1386. tcgprocinfo(current_procinfo).parse_body;
  1387. tcgprocinfo(current_procinfo).generate_code;
  1388. tcgprocinfo(current_procinfo).resetprocdef;
  1389. { save file pos for debuginfo }
  1390. current_module.mainfilepos:=current_procinfo.entrypos;
  1391. release_main_proc(pd);
  1392. { should we force unit initialization? }
  1393. if tstaticsymtable(current_module.localsymtable).needs_init_final then
  1394. begin
  1395. { initialize section }
  1396. gen_implicit_initfinal(uf_init,st);
  1397. { finalize section }
  1398. gen_implicit_initfinal(uf_finalize,st);
  1399. end;
  1400. { Add symbol to the exports section for win32 so smartlinking a
  1401. DLL will include the edata section }
  1402. if assigned(exportlib) and
  1403. (target_info.system in [system_i386_win32,system_i386_wdosx]) and
  1404. BinaryContainsExports then
  1405. asmlist[al_procedures].concat(tai_const.create_sym(exportlib.edatalabel));
  1406. If resourcestrings.ResStrCount>0 then
  1407. begin
  1408. resourcestrings.CreateResourceStringList;
  1409. { only write if no errors found }
  1410. if (Errorcount=0) then
  1411. resourcestrings.WriteResourceFile(ForceExtension(current_module.ppufilename^,'.rst'));
  1412. end;
  1413. { finalize? }
  1414. if token=_FINALIZATION then
  1415. begin
  1416. { set module options }
  1417. current_module.flags:=current_module.flags or uf_finalize;
  1418. { Compile the finalize }
  1419. pd:=create_main_proc(make_mangledname('',current_module.localsymtable,'finalize'),potype_unitfinalize,st);
  1420. pd.aliasnames.insert(make_mangledname('FINALIZE$',current_module.localsymtable,''));
  1421. tcgprocinfo(current_procinfo).parse_body;
  1422. tcgprocinfo(current_procinfo).generate_code;
  1423. tcgprocinfo(current_procinfo).resetprocdef;
  1424. release_main_proc(pd);
  1425. end;
  1426. { consume the last point }
  1427. consume(_POINT);
  1428. if (Errorcount=0) then
  1429. begin
  1430. { test static symtable }
  1431. tstoredsymtable(st).allsymbolsused;
  1432. tstoredsymtable(st).allprivatesused;
  1433. tstoredsymtable(st).check_forwards;
  1434. tstoredsymtable(st).checklabels;
  1435. tstoredsymtable(st).unchain_overloaded;
  1436. current_module.allunitsused;
  1437. end;
  1438. { leave when we got an error }
  1439. if (Errorcount>0) and not status.skip_error then
  1440. begin
  1441. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1442. status.skip_error:=true;
  1443. exit;
  1444. end;
  1445. { remove all unused units, this happends when units are removed
  1446. from the uses clause in the source and the ppu was already being loaded }
  1447. hp:=tmodule(loaded_units.first);
  1448. while assigned(hp) do
  1449. begin
  1450. hp2:=hp;
  1451. hp:=tmodule(hp.next);
  1452. if hp2.is_unit and
  1453. not assigned(hp2.globalsymtable) then
  1454. loaded_units.remove(hp2);
  1455. end;
  1456. { do we need to add the variants unit? }
  1457. maybeloadvariantsunit;
  1458. { generate debuginfo }
  1459. {$ifdef GDB}
  1460. write_gdb_info;
  1461. {$endif GDB}
  1462. { generate wrappers for interfaces }
  1463. gen_intf_wrappers(asmlist[al_procedures],current_module.localsymtable);
  1464. {$ifndef segment_threadvars}
  1465. { generate a list of threadvars }
  1466. InsertThreadvars;
  1467. {$endif}
  1468. { generate imports }
  1469. if current_module.uses_imports then
  1470. importlib.generatelib;
  1471. if islibrary or
  1472. (target_info.system in [system_i386_WIN32,system_i386_wdosx]) or
  1473. (target_info.system=system_i386_NETWARE) then
  1474. exportlib.generatelib;
  1475. { insert Tables and StackLength }
  1476. {$ifndef segment_threadvars}
  1477. insertThreadVarTablesTable;
  1478. {$endif}
  1479. insertResourceTablesTable;
  1480. insertinitfinaltable;
  1481. insertmemorysizes;
  1482. { Insert symbol to resource info }
  1483. InsertResourceInfo;
  1484. { create dwarf debuginfo }
  1485. create_dwarf;
  1486. { finish asmlist by adding segment starts }
  1487. // insertsegment;
  1488. { insert own objectfile }
  1489. insertobjectfile;
  1490. { assemble and link }
  1491. create_objectfile;
  1492. { release all local symtables that are not needed anymore }
  1493. free_localsymtables(current_module.localsymtable);
  1494. { leave when we got an error }
  1495. if (Errorcount>0) and not status.skip_error then
  1496. begin
  1497. Message1(unit_f_errors_in_unit,tostr(Errorcount));
  1498. status.skip_error:=true;
  1499. exit;
  1500. end;
  1501. { create the executable when we are at level 1 }
  1502. if (compile_level=1) then
  1503. begin
  1504. { insert all .o files from all loaded units }
  1505. hp:=tmodule(loaded_units.first);
  1506. while assigned(hp) do
  1507. begin
  1508. linker.AddModuleFiles(hp);
  1509. hp:=tmodule(hp.next);
  1510. end;
  1511. { write .def file }
  1512. if (cs_link_deffile in aktglobalswitches) then
  1513. deffile.writefile;
  1514. { finally we can create a executable }
  1515. if (not current_module.is_unit) then
  1516. begin
  1517. if DLLSource then
  1518. linker.MakeSharedLibrary
  1519. else
  1520. linker.MakeExecutable;
  1521. BinaryContainsExports:=false;
  1522. end;
  1523. end;
  1524. end;
  1525. end.