ngenutil.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. {
  2. Copyright (c) 1998-2011 by Florian Klaempfl
  3. Generic version of some node tree helper routines that can be overridden
  4. by cpu-specific versions
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ngenutil;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,symtype,symsym,symconst,symdef;
  23. type
  24. tnodeutils = class
  25. class function call_fail_node:tnode; virtual;
  26. class function initialize_data_node(p:tnode):tnode; virtual;
  27. class function finalize_data_node(p:tnode):tnode; virtual;
  28. { returns true if the unit requires an initialisation section (e.g.,
  29. to force class constructors for the JVM target to initialise global
  30. records/arrays) }
  31. class function force_init: boolean; virtual;
  32. { idem for finalization }
  33. class function force_final: boolean; virtual;
  34. { called after parsing a routine with the code of the entire routine
  35. as argument; can be used to modify the node tree. By default handles
  36. insertion of code for systems that perform the typed constant
  37. initialisation via the node tree }
  38. class function wrap_proc_body(pd: tprocdef; n: tnode): tnode; virtual;
  39. class procedure insertbssdata(sym : tstaticvarsym); virtual;
  40. class function create_main_procdef(const name: string; potype:tproctypeoption; ps: tprocsym):tdef; virtual;
  41. class procedure InsertInitFinalTable; virtual;
  42. public
  43. class procedure InsertThreadvarTablesTable; virtual;
  44. class procedure InsertThreadvars; virtual;
  45. class procedure InsertWideInitsTablesTable; virtual;
  46. class procedure InsertWideInits; virtual;
  47. class procedure InsertResourceTablesTable; virtual;
  48. class procedure InsertResourceInfo(ResourcesUsed : boolean); virtual;
  49. class procedure InsertMemorySizes; virtual;
  50. strict protected
  51. class procedure add_main_procdef_paras(pd: tdef); virtual;
  52. end;
  53. tnodeutilsclass = class of tnodeutils;
  54. const
  55. cnodeutils: tnodeutilsclass = tnodeutils;
  56. implementation
  57. uses
  58. verbose,version,globtype,globals,cclasses,cutils,constexp,
  59. scanner,systems,procinfo,fmodule,
  60. aasmbase,aasmdata,aasmtai,
  61. symbase,symtable,defutil,
  62. nadd,nbas,ncal,ncnv,ncon,nflw,nld,nmem,nobj,nutils,
  63. ppu,
  64. pass_1;
  65. class function tnodeutils.call_fail_node:tnode;
  66. var
  67. para : tcallparanode;
  68. newstatement : tstatementnode;
  69. srsym : tsym;
  70. begin
  71. result:=internalstatements(newstatement);
  72. { call fail helper and exit normal }
  73. if is_class(current_structdef) then
  74. begin
  75. srsym:=search_struct_member(current_structdef,'FREEINSTANCE');
  76. if assigned(srsym) and
  77. (srsym.typ=procsym) then
  78. begin
  79. { if self<>0 and vmt<>0 then freeinstance }
  80. addstatement(newstatement,cifnode.create(
  81. caddnode.create(andn,
  82. caddnode.create(unequaln,
  83. load_self_pointer_node,
  84. cnilnode.create),
  85. caddnode.create(unequaln,
  86. load_vmt_pointer_node,
  87. cnilnode.create)),
  88. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
  89. nil));
  90. end
  91. else
  92. internalerror(200305108);
  93. end
  94. else
  95. if is_object(current_structdef) then
  96. begin
  97. { parameter 3 : vmt_offset }
  98. { parameter 2 : pointer to vmt }
  99. { parameter 1 : self pointer }
  100. para:=ccallparanode.create(
  101. cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
  102. ccallparanode.create(
  103. ctypeconvnode.create_internal(
  104. load_vmt_pointer_node,
  105. voidpointertype),
  106. ccallparanode.create(
  107. ctypeconvnode.create_internal(
  108. load_self_pointer_node,
  109. voidpointertype),
  110. nil)));
  111. addstatement(newstatement,
  112. ccallnode.createintern('fpc_help_fail',para));
  113. end
  114. else
  115. internalerror(200305132);
  116. { self:=nil }
  117. addstatement(newstatement,cassignmentnode.create(
  118. load_self_pointer_node,
  119. cnilnode.create));
  120. { exit }
  121. addstatement(newstatement,cexitnode.create(nil));
  122. end;
  123. class function tnodeutils.initialize_data_node(p:tnode):tnode;
  124. begin
  125. if not assigned(p.resultdef) then
  126. typecheckpass(p);
  127. if is_ansistring(p.resultdef) or
  128. is_wide_or_unicode_string(p.resultdef) or
  129. is_interfacecom_or_dispinterface(p.resultdef) or
  130. is_dynamic_array(p.resultdef) then
  131. begin
  132. result:=cassignmentnode.create(
  133. ctypeconvnode.create_internal(p,voidpointertype),
  134. cnilnode.create
  135. );
  136. end
  137. else
  138. begin
  139. result:=ccallnode.createintern('fpc_initialize',
  140. ccallparanode.create(
  141. caddrnode.create_internal(
  142. crttinode.create(
  143. tstoreddef(p.resultdef),initrtti,rdt_normal)),
  144. ccallparanode.create(
  145. caddrnode.create_internal(p),
  146. nil)));
  147. end;
  148. end;
  149. class function tnodeutils.finalize_data_node(p:tnode):tnode;
  150. var
  151. newstatement : tstatementnode;
  152. begin
  153. if not assigned(p.resultdef) then
  154. typecheckpass(p);
  155. if is_ansistring(p.resultdef) then
  156. begin
  157. result:=internalstatements(newstatement);
  158. addstatement(newstatement,ccallnode.createintern('fpc_ansistr_decr_ref',
  159. ccallparanode.create(
  160. ctypeconvnode.create_internal(p,voidpointertype),
  161. nil)));
  162. addstatement(newstatement,cassignmentnode.create(
  163. ctypeconvnode.create_internal(p.getcopy,voidpointertype),
  164. cnilnode.create
  165. ));
  166. end
  167. else if is_widestring(p.resultdef) then
  168. begin
  169. result:=internalstatements(newstatement);
  170. addstatement(newstatement,ccallnode.createintern('fpc_widestr_decr_ref',
  171. ccallparanode.create(
  172. ctypeconvnode.create_internal(p,voidpointertype),
  173. nil)));
  174. addstatement(newstatement,cassignmentnode.create(
  175. ctypeconvnode.create_internal(p.getcopy,voidpointertype),
  176. cnilnode.create
  177. ));
  178. end
  179. else if is_unicodestring(p.resultdef) then
  180. begin
  181. result:=internalstatements(newstatement);
  182. addstatement(newstatement,ccallnode.createintern('fpc_unicodestr_decr_ref',
  183. ccallparanode.create(
  184. ctypeconvnode.create_internal(p,voidpointertype),
  185. nil)));
  186. addstatement(newstatement,cassignmentnode.create(
  187. ctypeconvnode.create_internal(p.getcopy,voidpointertype),
  188. cnilnode.create
  189. ));
  190. end
  191. else if is_interfacecom_or_dispinterface(p.resultdef) then
  192. begin
  193. result:=internalstatements(newstatement);
  194. addstatement(newstatement,ccallnode.createintern('fpc_intf_decr_ref',
  195. ccallparanode.create(
  196. ctypeconvnode.create_internal(p,voidpointertype),
  197. nil)));
  198. addstatement(newstatement,cassignmentnode.create(
  199. ctypeconvnode.create_internal(p.getcopy,voidpointertype),
  200. cnilnode.create
  201. ));
  202. end
  203. else
  204. result:=ccallnode.createintern('fpc_finalize',
  205. ccallparanode.create(
  206. caddrnode.create_internal(
  207. crttinode.create(
  208. tstoreddef(p.resultdef),initrtti,rdt_normal)),
  209. ccallparanode.create(
  210. caddrnode.create_internal(p),
  211. nil)));
  212. end;
  213. class function tnodeutils.force_init: boolean;
  214. begin
  215. result:=
  216. (target_info.system in systems_typed_constants_node_init) and
  217. assigned(current_module.tcinitcode);
  218. end;
  219. class function tnodeutils.force_final: boolean;
  220. begin
  221. result:=false;
  222. end;
  223. class function tnodeutils.wrap_proc_body(pd: tprocdef; n: tnode): tnode;
  224. var
  225. stat: tstatementnode;
  226. block: tnode;
  227. psym: tsym;
  228. tcinitproc: tprocdef;
  229. begin
  230. result:=n;
  231. if target_info.system in systems_typed_constants_node_init then
  232. begin
  233. case pd.proctypeoption of
  234. potype_class_constructor:
  235. begin
  236. { even though the initialisation code for typed constants may
  237. not yet be complete at this point (there may be more inside
  238. method definitions coming after this class constructor), the
  239. ones from inside the class definition have already been parsed.
  240. in case of {$j-}, these are marked "final" in Java and such
  241. static fields must be initialsed in the class constructor
  242. itself -> add them here }
  243. block:=internalstatements(stat);
  244. if assigned(pd.struct.tcinitcode) then
  245. begin
  246. addstatement(stat,pd.struct.tcinitcode);
  247. pd.struct.tcinitcode:=nil;
  248. end;
  249. psym:=tsym(pd.struct.symtable.find('FPC_INIT_TYPED_CONSTS_HELPER'));
  250. if assigned(psym) then
  251. begin
  252. if (psym.typ<>procsym) or
  253. (tprocsym(psym).procdeflist.count<>1) then
  254. internalerror(2011040301);
  255. tcinitproc:=tprocdef(tprocsym(psym).procdeflist[0]);
  256. addstatement(stat,ccallnode.create(nil,tprocsym(psym),
  257. pd.struct.symtable,nil,[]));
  258. end;
  259. addstatement(stat,result);
  260. result:=block
  261. end;
  262. potype_unitinit:
  263. begin
  264. if assigned(current_module.tcinitcode) then
  265. begin
  266. block:=internalstatements(stat);
  267. addstatement(stat,tnode(current_module.tcinitcode));
  268. current_module.tcinitcode:=nil;
  269. addstatement(stat,result);
  270. result:=block;
  271. end;
  272. end;
  273. else case pd.synthetickind of
  274. tsk_tcinit:
  275. begin
  276. if assigned(pd.struct.tcinitcode) then
  277. begin
  278. block:=internalstatements(stat);
  279. addstatement(stat,pd.struct.tcinitcode);
  280. pd.struct.tcinitcode:=nil;
  281. addstatement(stat,result);
  282. result:=block
  283. end
  284. end;
  285. end;
  286. end;
  287. end;
  288. end;
  289. class procedure tnodeutils.insertbssdata(sym: tstaticvarsym);
  290. var
  291. l : asizeint;
  292. varalign : shortint;
  293. storefilepos : tfileposinfo;
  294. list : TAsmList;
  295. sectype : TAsmSectiontype;
  296. begin
  297. storefilepos:=current_filepos;
  298. current_filepos:=sym.fileinfo;
  299. l:=sym.getsize;
  300. varalign:=sym.vardef.alignment;
  301. if (varalign=0) then
  302. varalign:=var_align_size(l)
  303. else
  304. varalign:=var_align(varalign);
  305. if tf_section_threadvars in target_info.flags then
  306. begin
  307. if (vo_is_thread_var in sym.varoptions) then
  308. begin
  309. list:=current_asmdata.asmlists[al_threadvars];
  310. sectype:=sec_threadvar;
  311. end
  312. else
  313. begin
  314. list:=current_asmdata.asmlists[al_globals];
  315. sectype:=sec_bss;
  316. end;
  317. end
  318. else
  319. begin
  320. if (vo_is_thread_var in sym.varoptions) then
  321. begin
  322. inc(l,sizeof(pint));
  323. { it doesn't help to set a higher alignment, as }
  324. { the first sizeof(pint) bytes field will offset }
  325. { everything anyway }
  326. varalign:=sizeof(pint);
  327. end;
  328. list:=current_asmdata.asmlists[al_globals];
  329. sectype:=sec_bss;
  330. end;
  331. maybe_new_object_file(list);
  332. if vo_has_section in sym.varoptions then
  333. new_section(list,sec_user,sym.section,varalign)
  334. else
  335. new_section(list,sectype,lower(sym.mangledname),varalign);
  336. if (sym.owner.symtabletype=globalsymtable) or
  337. create_smartlink or
  338. DLLSource or
  339. (assigned(current_procinfo) and
  340. (po_inline in current_procinfo.procdef.procoptions)) or
  341. (vo_is_public in sym.varoptions) then
  342. list.concat(Tai_datablock.create_global(sym.mangledname,l))
  343. else
  344. list.concat(Tai_datablock.create(sym.mangledname,l));
  345. current_filepos:=storefilepos;
  346. end;
  347. class function tnodeutils.create_main_procdef(const name: string; potype: tproctypeoption; ps: tprocsym): tdef;
  348. var
  349. pd: tprocdef;
  350. begin
  351. pd:=tprocdef.create(main_program_level);
  352. pd.procsym:=ps;
  353. ps.ProcdefList.Add(pd);
  354. include(pd.procoptions,po_global);
  355. { set procdef options }
  356. pd.proctypeoption:=potype;
  357. pd.proccalloption:=pocall_default;
  358. include(pd.procoptions,po_hascallingconvention);
  359. pd.forwarddef:=false;
  360. { may be required to calculate the mangled name }
  361. add_main_procdef_paras(pd);
  362. pd.setmangledname(name);
  363. pd.aliasnames.insert(pd.mangledname);
  364. result:=pd;
  365. end;
  366. procedure AddToStructInits(p:TObject;arg:pointer);
  367. var
  368. StructList: TFPList absolute arg;
  369. begin
  370. if (tdef(p).typ in [objectdef,recorddef]) and
  371. ([oo_has_class_constructor,oo_has_class_destructor] * tabstractrecorddef(p).objectoptions <> []) then
  372. StructList.Add(p);
  373. end;
  374. class procedure tnodeutils.InsertInitFinalTable;
  375. var
  376. hp : tused_unit;
  377. unitinits : TAsmList;
  378. count : longint;
  379. procedure write_struct_inits(u: tmodule);
  380. var
  381. i: integer;
  382. structlist: TFPList;
  383. pd: tprocdef;
  384. begin
  385. structlist := TFPList.Create;
  386. if assigned(u.globalsymtable) then
  387. u.globalsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
  388. u.localsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
  389. { write structures }
  390. for i := 0 to structlist.Count - 1 do
  391. begin
  392. pd := tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_constructor);
  393. if assigned(pd) then
  394. unitinits.concat(Tai_const.Createname(pd.mangledname,0))
  395. else
  396. unitinits.concat(Tai_const.Create_pint(0));
  397. pd := tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_destructor);
  398. if assigned(pd) then
  399. unitinits.concat(Tai_const.Createname(pd.mangledname,0))
  400. else
  401. unitinits.concat(Tai_const.Create_pint(0));
  402. inc(count);
  403. end;
  404. structlist.free;
  405. end;
  406. begin
  407. unitinits:=TAsmList.Create;
  408. count:=0;
  409. hp:=tused_unit(usedunits.first);
  410. while assigned(hp) do
  411. begin
  412. { insert class constructors/destructors of the unit }
  413. if (hp.u.flags and uf_classinits) <> 0 then
  414. write_struct_inits(hp.u);
  415. { call the unit init code and make it external }
  416. if (hp.u.flags and (uf_init or uf_finalize))<>0 then
  417. begin
  418. if (hp.u.flags and uf_init)<>0 then
  419. unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',hp.u.globalsymtable,''),0))
  420. else
  421. unitinits.concat(Tai_const.Create_sym(nil));
  422. if (hp.u.flags and uf_finalize)<>0 then
  423. unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',hp.u.globalsymtable,''),0))
  424. else
  425. unitinits.concat(Tai_const.Create_sym(nil));
  426. inc(count);
  427. end;
  428. hp:=tused_unit(hp.next);
  429. end;
  430. { insert class constructors/destructor of the program }
  431. if (current_module.flags and uf_classinits) <> 0 then
  432. write_struct_inits(current_module);
  433. { Insert initialization/finalization of the program }
  434. if (current_module.flags and (uf_init or uf_finalize))<>0 then
  435. begin
  436. if (current_module.flags and uf_init)<>0 then
  437. unitinits.concat(Tai_const.Createname(make_mangledname('INIT$',current_module.localsymtable,''),0))
  438. else
  439. unitinits.concat(Tai_const.Create_sym(nil));
  440. if (current_module.flags and uf_finalize)<>0 then
  441. unitinits.concat(Tai_const.Createname(make_mangledname('FINALIZE$',current_module.localsymtable,''),0))
  442. else
  443. unitinits.concat(Tai_const.Create_sym(nil));
  444. inc(count);
  445. end;
  446. { Insert TableCount,InitCount at start }
  447. unitinits.insert(Tai_const.Create_32bit(0));
  448. unitinits.insert(Tai_const.Create_32bit(count));
  449. { Add to data segment }
  450. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  451. new_section(current_asmdata.asmlists[al_globals],sec_data,'INITFINAL',sizeof(pint));
  452. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('INITFINAL',AT_DATA,0));
  453. current_asmdata.asmlists[al_globals].concatlist(unitinits);
  454. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('INITFINAL'));
  455. unitinits.free;
  456. end;
  457. class procedure tnodeutils.InsertThreadvarTablesTable;
  458. var
  459. hp : tused_unit;
  460. ltvTables : TAsmList;
  461. count : longint;
  462. begin
  463. if (tf_section_threadvars in target_info.flags) then
  464. exit;
  465. ltvTables:=TAsmList.Create;
  466. count:=0;
  467. hp:=tused_unit(usedunits.first);
  468. while assigned(hp) do
  469. begin
  470. If (hp.u.flags and uf_threadvars)=uf_threadvars then
  471. begin
  472. ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',hp.u.globalsymtable,''),0));
  473. inc(count);
  474. end;
  475. hp:=tused_unit(hp.next);
  476. end;
  477. { Add program threadvars, if any }
  478. If (current_module.flags and uf_threadvars)=uf_threadvars then
  479. begin
  480. ltvTables.concat(Tai_const.Createname(make_mangledname('THREADVARLIST',current_module.localsymtable,''),0));
  481. inc(count);
  482. end;
  483. { Insert TableCount at start }
  484. ltvTables.insert(Tai_const.Create_32bit(count));
  485. { insert in data segment }
  486. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  487. new_section(current_asmdata.asmlists[al_globals],sec_data,'FPC_THREADVARTABLES',sizeof(pint));
  488. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('FPC_THREADVARTABLES',AT_DATA,0));
  489. current_asmdata.asmlists[al_globals].concatlist(ltvTables);
  490. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('FPC_THREADVARTABLES'));
  491. ltvTables.free;
  492. end;
  493. procedure AddToThreadvarList(p:TObject;arg:pointer);
  494. var
  495. ltvTable : TAsmList;
  496. begin
  497. ltvTable:=TAsmList(arg);
  498. if (tsym(p).typ=staticvarsym) and
  499. (vo_is_thread_var in tstaticvarsym(p).varoptions) then
  500. begin
  501. { address of threadvar }
  502. ltvTable.concat(tai_const.Createname(tstaticvarsym(p).mangledname,0));
  503. { size of threadvar }
  504. ltvTable.concat(tai_const.create_32bit(tstaticvarsym(p).getsize));
  505. end;
  506. end;
  507. class procedure tnodeutils.InsertThreadvars;
  508. var
  509. s : string;
  510. ltvTable : TAsmList;
  511. begin
  512. if (tf_section_threadvars in target_info.flags) then
  513. exit;
  514. ltvTable:=TAsmList.create;
  515. if assigned(current_module.globalsymtable) then
  516. current_module.globalsymtable.SymList.ForEachCall(@AddToThreadvarList,ltvTable);
  517. current_module.localsymtable.SymList.ForEachCall(@AddToThreadvarList,ltvTable);
  518. if ltvTable.first<>nil then
  519. begin
  520. s:=make_mangledname('THREADVARLIST',current_module.localsymtable,'');
  521. { end of the list marker }
  522. ltvTable.concat(tai_const.create_sym(nil));
  523. { add to datasegment }
  524. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  525. new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
  526. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  527. current_asmdata.asmlists[al_globals].concatlist(ltvTable);
  528. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
  529. current_module.flags:=current_module.flags or uf_threadvars;
  530. end;
  531. ltvTable.Free;
  532. end;
  533. class procedure tnodeutils.InsertWideInitsTablesTable;
  534. var
  535. hp: tused_unit;
  536. lwiTables: TAsmList;
  537. count: longint;
  538. begin
  539. lwiTables:=TAsmList.Create;
  540. count:=0;
  541. hp:=tused_unit(usedunits.first);
  542. while assigned(hp) do
  543. begin
  544. if (hp.u.flags and uf_wideinits)=uf_wideinits then
  545. begin
  546. lwiTables.concat(Tai_const.Createname(make_mangledname('WIDEINITS',hp.u.globalsymtable,''),0));
  547. inc(count);
  548. end;
  549. hp:=tused_unit(hp.next);
  550. end;
  551. { Add program widestring consts, if any }
  552. if (current_module.flags and uf_wideinits)=uf_wideinits then
  553. begin
  554. lwiTables.concat(Tai_const.Createname(make_mangledname('WIDEINITS',current_module.localsymtable,''),0));
  555. inc(count);
  556. end;
  557. { Insert TableCount at start }
  558. lwiTables.insert(Tai_const.Create_32bit(count));
  559. { insert in data segment }
  560. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  561. new_section(current_asmdata.asmlists[al_globals],sec_data,'FPC_WIDEINITTABLES',sizeof(pint));
  562. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('FPC_WIDEINITTABLES',AT_DATA,0));
  563. current_asmdata.asmlists[al_globals].concatlist(lwiTables);
  564. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('FPC_WIDEINITTABLES'));
  565. lwiTables.free;
  566. end;
  567. class procedure tnodeutils.InsertWideInits;
  568. var
  569. s: string;
  570. item: TTCInitItem;
  571. begin
  572. item:=TTCInitItem(current_asmdata.WideInits.First);
  573. if item=nil then
  574. exit;
  575. s:=make_mangledname('WIDEINITS',current_module.localsymtable,'');
  576. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  577. new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
  578. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  579. repeat
  580. { optimize away unused local/static symbols }
  581. if (item.sym.refs>0) or (item.sym.owner.symtabletype=globalsymtable) then
  582. begin
  583. { address to initialize }
  584. current_asmdata.asmlists[al_globals].concat(Tai_const.createname(item.sym.mangledname, item.offset));
  585. { value with which to initialize }
  586. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(item.datalabel));
  587. end;
  588. item:=TTCInitItem(item.Next);
  589. until item=nil;
  590. { end-of-list marker }
  591. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  592. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
  593. current_module.flags:=current_module.flags or uf_wideinits;
  594. end;
  595. class procedure tnodeutils.InsertResourceTablesTable;
  596. var
  597. hp : tmodule;
  598. ResourceStringTables : tasmlist;
  599. count : longint;
  600. begin
  601. ResourceStringTables:=tasmlist.Create;
  602. count:=0;
  603. hp:=tmodule(loaded_units.first);
  604. while assigned(hp) do
  605. begin
  606. If (hp.flags and uf_has_resourcestrings)=uf_has_resourcestrings then
  607. begin
  608. ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESSTR',hp.localsymtable,'START'),0));
  609. ResourceStringTables.concat(Tai_const.Createname(make_mangledname('RESSTR',hp.localsymtable,'END'),0));
  610. inc(count);
  611. end;
  612. hp:=tmodule(hp.next);
  613. end;
  614. { Insert TableCount at start }
  615. ResourceStringTables.insert(Tai_const.Create_pint(count));
  616. { Add to data segment }
  617. maybe_new_object_file(current_asmdata.AsmLists[al_globals]);
  618. new_section(current_asmdata.AsmLists[al_globals],sec_data,'FPC_RESOURCESTRINGTABLES',sizeof(pint));
  619. current_asmdata.AsmLists[al_globals].concat(Tai_symbol.Createname_global('FPC_RESOURCESTRINGTABLES',AT_DATA,0));
  620. current_asmdata.AsmLists[al_globals].concatlist(ResourceStringTables);
  621. current_asmdata.AsmLists[al_globals].concat(Tai_symbol_end.Createname('FPC_RESOURCESTRINGTABLES'));
  622. ResourceStringTables.free;
  623. end;
  624. class procedure tnodeutils.InsertResourceInfo(ResourcesUsed: boolean);
  625. var
  626. ResourceInfo : TAsmList;
  627. begin
  628. if (target_res.id in [res_elf,res_macho]) then
  629. begin
  630. ResourceInfo:=TAsmList.Create;
  631. maybe_new_object_file(ResourceInfo);
  632. new_section(ResourceInfo,sec_data,'FPC_RESLOCATION',sizeof(aint));
  633. ResourceInfo.concat(Tai_symbol.Createname_global('FPC_RESLOCATION',AT_DATA,0));
  634. if ResourcesUsed then
  635. { Valid pointer to resource information }
  636. ResourceInfo.concat(Tai_const.Createname('FPC_RESSYMBOL',0))
  637. else
  638. { Nil pointer to resource information }
  639. {$IFDEF CPU32}
  640. ResourceInfo.Concat(Tai_const.Create_32bit(0));
  641. {$ELSE}
  642. ResourceInfo.Concat(Tai_const.Create_64bit(0));
  643. {$ENDIF}
  644. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  645. current_asmdata.asmlists[al_globals].concatlist(ResourceInfo);
  646. ResourceInfo.free;
  647. end;
  648. end;
  649. class procedure tnodeutils.InsertMemorySizes;
  650. {$IFDEF POWERPC}
  651. var
  652. stkcookie: string;
  653. {$ENDIF POWERPC}
  654. begin
  655. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  656. { Insert Ident of the compiler in the .fpc.version section }
  657. new_section(current_asmdata.asmlists[al_globals],sec_fpc,'version',const_align(32));
  658. current_asmdata.asmlists[al_globals].concat(Tai_string.Create('FPC '+full_version_string+
  659. ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname));
  660. if not(tf_no_generic_stackcheck in target_info.flags) then
  661. begin
  662. { stacksize can be specified and is now simulated }
  663. new_section(current_asmdata.asmlists[al_globals],sec_data,'__stklen', sizeof(pint));
  664. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__stklen',AT_DATA,sizeof(pint)));
  665. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(stacksize));
  666. end;
  667. {$IFDEF POWERPC}
  668. { AmigaOS4 "stack cookie" support }
  669. if ( target_info.system = system_powerpc_amiga ) then
  670. begin
  671. { this symbol is needed to ignite powerpc amigaos' }
  672. { stack allocation magic for us with the given stack size. }
  673. { note: won't work for m68k amigaos or morphos. (KB) }
  674. str(stacksize,stkcookie);
  675. stkcookie:='$STACK: '+stkcookie+#0;
  676. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  677. new_section(current_asmdata.asmlists[al_globals],sec_data,'__stack_cookie',length(stkcookie));
  678. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__stack_cookie',AT_DATA,length(stkcookie)));
  679. current_asmdata.asmlists[al_globals].concat(Tai_string.Create(stkcookie));
  680. end;
  681. {$ENDIF POWERPC}
  682. { Initial heapsize }
  683. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  684. new_section(current_asmdata.asmlists[al_globals],sec_data,'__heapsize',sizeof(pint));
  685. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__heapsize',AT_DATA,sizeof(pint)));
  686. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_pint(heapsize));
  687. { Initial heapsize }
  688. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  689. new_section(current_asmdata.asmlists[al_globals],sec_data,'__fpc_valgrind',sizeof(boolean));
  690. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('__fpc_valgrind',AT_DATA,sizeof(boolean)));
  691. current_asmdata.asmlists[al_globals].concat(Tai_const.create_8bit(byte(cs_gdb_valgrind in current_settings.globalswitches)));
  692. end;
  693. class procedure tnodeutils.add_main_procdef_paras(pd: tdef);
  694. begin
  695. { no parameters by default }
  696. end;
  697. end.