psub.pas 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl, Daniel Mantione
  4. Does the parsing and codegeneration at subroutine level
  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 psub;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cclasses,globals,
  23. node,nbas,
  24. symdef,procinfo;
  25. type
  26. tcgprocinfo = class(tprocinfo)
  27. private
  28. procedure add_entry_exit_code;
  29. public
  30. { code for the subroutine as tree }
  31. code : tnode;
  32. { positions in the tree for init/final }
  33. entry_asmnode,
  34. loadpara_asmnode,
  35. exitlabel_asmnode,
  36. init_asmnode,
  37. final_asmnode : tasmnode;
  38. { list to store the procinfo's of the nested procedures }
  39. nestedprocs : tlinkedlist;
  40. constructor create(aparent:tprocinfo);override;
  41. destructor destroy;override;
  42. procedure generate_code;
  43. procedure resetprocdef;
  44. procedure add_to_symtablestack;
  45. procedure remove_from_symtablestack;
  46. procedure parse_body;
  47. end;
  48. procedure printnode_reset;
  49. { reads the declaration blocks }
  50. procedure read_declarations(islibrary : boolean);
  51. { reads declarations in the interface part of a unit }
  52. procedure read_interface_declarations;
  53. implementation
  54. uses
  55. { common }
  56. cutils,
  57. { global }
  58. globtype,tokens,verbose,comphook,
  59. systems,
  60. { aasm }
  61. cpubase,aasmbase,aasmtai,
  62. { symtable }
  63. symconst,symbase,symsym,symtype,symtable,defutil,
  64. paramgr,
  65. ppu,fmodule,
  66. { pass 1 }
  67. nutils,nld,ncal,ncon,nflw,nadd,ncnv,nmem,
  68. pass_1,
  69. {$ifdef state_tracking}
  70. nstate,
  71. {$endif state_tracking}
  72. { pass 2 }
  73. {$ifndef NOPASS2}
  74. pass_2,
  75. {$endif}
  76. { parser }
  77. scanner,
  78. pbase,pstatmnt,pdecl,pdecsub,pexports,
  79. { codegen }
  80. tgobj,cgobj,
  81. ncgutil,regvars
  82. {$ifdef arm}
  83. ,aasmcpu
  84. {$endif arm}
  85. {$ifndef NOOPT}
  86. {$ifdef i386}
  87. ,aopt386
  88. {$else i386}
  89. ,aoptcpu
  90. {$endif i386}
  91. {$endif}
  92. ;
  93. {****************************************************************************
  94. PROCEDURE/FUNCTION BODY PARSING
  95. ****************************************************************************}
  96. procedure initializevars(p:tnamedindexitem;arg:pointer);
  97. var
  98. b : tblocknode;
  99. begin
  100. if tsym(p).typ<>varsym then
  101. exit;
  102. with tvarsym(p) do
  103. begin
  104. if assigned(defaultconstsym) then
  105. begin
  106. b:=tblocknode(arg);
  107. b.left:=cstatementnode.create(
  108. cassignmentnode.create(
  109. cloadnode.create(tsym(p),tsym(p).owner),
  110. cloadnode.create(defaultconstsym,defaultconstsym.owner)),
  111. b.left);
  112. end;
  113. end;
  114. end;
  115. procedure check_finalize_paras(p : tnamedindexitem;arg:pointer);
  116. begin
  117. if (tsym(p).typ=varsym) and
  118. (tvarsym(p).varspez=vs_value) and
  119. not is_class(tvarsym(p).vartype.def) and
  120. tvarsym(p).vartype.def.needs_inittable then
  121. include(current_procinfo.flags,pi_needs_implicit_finally);
  122. end;
  123. procedure check_finalize_locals(p : tnamedindexitem;arg:pointer);
  124. begin
  125. case tsym(p).typ of
  126. varsym :
  127. begin
  128. if (tvarsym(p).refs>0) and
  129. not(vo_is_funcret in tvarsym(p).varoptions) and
  130. not(is_class(tvarsym(p).vartype.def)) and
  131. tvarsym(p).vartype.def.needs_inittable then
  132. include(current_procinfo.flags,pi_needs_implicit_finally);
  133. end;
  134. typedconstsym :
  135. begin
  136. if ttypedconstsym(p).typedconsttype.def.needs_inittable then
  137. include(current_procinfo.flags,pi_needs_implicit_finally);
  138. end;
  139. end;
  140. end;
  141. function block(islibrary : boolean) : tnode;
  142. begin
  143. { parse const,types and vars }
  144. read_declarations(islibrary);
  145. { do we have an assembler block without the po_assembler?
  146. we should allow this for Delphi compatibility (PFV) }
  147. if (token=_ASM) and (m_delphi in aktmodeswitches) then
  148. include(current_procinfo.procdef.procoptions,po_assembler);
  149. { Handle assembler block different }
  150. if (po_assembler in current_procinfo.procdef.procoptions) then
  151. begin
  152. block:=assembler_block;
  153. exit;
  154. end;
  155. {Unit initialization?.}
  156. if (
  157. assigned(current_procinfo.procdef.localst) and
  158. (current_procinfo.procdef.localst.symtablelevel=main_program_level) and
  159. (current_module.is_unit)
  160. ) or
  161. islibrary then
  162. begin
  163. if (token=_END) then
  164. begin
  165. consume(_END);
  166. { We need at least a node, else the entry/exit code is not
  167. generated and thus no PASCALMAIN symbol which we need (PFV) }
  168. if islibrary then
  169. block:=cnothingnode.create
  170. else
  171. block:=nil;
  172. end
  173. else
  174. begin
  175. if token=_INITIALIZATION then
  176. begin
  177. { The library init code is already called and does not
  178. need to be in the initfinal table (PFV) }
  179. if not islibrary then
  180. current_module.flags:=current_module.flags or uf_init;
  181. block:=statement_block(_INITIALIZATION);
  182. end
  183. else if (token=_FINALIZATION) then
  184. begin
  185. if (current_module.flags and uf_finalize)<>0 then
  186. block:=statement_block(_FINALIZATION)
  187. else
  188. begin
  189. { can we allow no INITIALIZATION for DLL ??
  190. I think it should work PM }
  191. block:=nil;
  192. exit;
  193. end;
  194. end
  195. else
  196. begin
  197. { The library init code is already called and does not
  198. need to be in the initfinal table (PFV) }
  199. if not islibrary then
  200. current_module.flags:=current_module.flags or uf_init;
  201. block:=statement_block(_BEGIN);
  202. end;
  203. end;
  204. end
  205. else
  206. begin
  207. block:=statement_block(_BEGIN);
  208. if symtablestack.symtabletype=localsymtable then
  209. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}initializevars,block);
  210. end;
  211. end;
  212. {****************************************************************************
  213. PROCEDURE/FUNCTION COMPILING
  214. ****************************************************************************}
  215. procedure printnode_reset;
  216. begin
  217. assign(printnodefile,treelogfilename);
  218. {$I-}
  219. rewrite(printnodefile);
  220. {$I+}
  221. if ioresult<>0 then
  222. begin
  223. Comment(V_Error,'Error creating '+treelogfilename);
  224. exit;
  225. end;
  226. close(printnodefile);
  227. end;
  228. procedure printnode_procdef(pd:tprocdef);
  229. begin
  230. assign(printnodefile,treelogfilename);
  231. {$I-}
  232. append(printnodefile);
  233. if ioresult<>0 then
  234. rewrite(printnodefile);
  235. {$I+}
  236. if ioresult<>0 then
  237. begin
  238. Comment(V_Error,'Error creating '+treelogfilename);
  239. exit;
  240. end;
  241. writeln(printnodefile);
  242. writeln(printnodefile,'*******************************************************************************');
  243. writeln(printnodefile,current_procinfo.procdef.fullprocname(false));
  244. writeln(printnodefile,'*******************************************************************************');
  245. printnode(printnodefile,pd.inlininginfo^.code);
  246. close(printnodefile);
  247. end;
  248. function generate_bodyentry_block:tnode;
  249. var
  250. srsym : tsym;
  251. para : tcallparanode;
  252. newstatement : tstatementnode;
  253. htype : ttype;
  254. begin
  255. result:=internalstatements(newstatement);
  256. if assigned(current_procinfo.procdef._class) then
  257. begin
  258. { a constructor needs a help procedure }
  259. if (current_procinfo.procdef.proctypeoption=potype_constructor) then
  260. begin
  261. if is_class(current_procinfo.procdef._class) then
  262. begin
  263. include(current_procinfo.flags,pi_needs_implicit_finally);
  264. srsym:=search_class_member(current_procinfo.procdef._class,'NEWINSTANCE');
  265. if assigned(srsym) and
  266. (srsym.typ=procsym) then
  267. begin
  268. { if vmt<>0 then newinstance }
  269. addstatement(newstatement,cifnode.create(
  270. caddnode.create(unequaln,
  271. load_vmt_pointer_node,
  272. cnilnode.create),
  273. cassignmentnode.create(
  274. ctypeconvnode.create_explicit(
  275. load_self_pointer_node,
  276. voidpointertype),
  277. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node,[])),
  278. nil));
  279. end
  280. else
  281. internalerror(200305108);
  282. end
  283. else
  284. if is_object(current_procinfo.procdef._class) then
  285. begin
  286. htype.setdef(current_procinfo.procdef._class);
  287. htype.setdef(tpointerdef.create(htype));
  288. { parameter 3 : vmt_offset }
  289. { parameter 2 : address of pointer to vmt,
  290. this is required to allow setting the vmt to -1 to indicate
  291. that memory was allocated }
  292. { parameter 1 : self pointer }
  293. para:=ccallparanode.create(
  294. cordconstnode.create(current_procinfo.procdef._class.vmt_offset,s32inttype,false),
  295. ccallparanode.create(
  296. ctypeconvnode.create_explicit(
  297. load_vmt_pointer_node,
  298. voidpointertype),
  299. ccallparanode.create(
  300. ctypeconvnode.create_explicit(
  301. load_self_pointer_node,
  302. voidpointertype),
  303. nil)));
  304. addstatement(newstatement,cassignmentnode.create(
  305. ctypeconvnode.create_explicit(
  306. load_self_pointer_node,
  307. voidpointertype),
  308. ccallnode.createintern('fpc_help_constructor',para)));
  309. end
  310. else
  311. internalerror(200305103);
  312. { if self=nil then exit
  313. calling fail instead of exit is useless because
  314. there is nothing to dispose (PFV) }
  315. addstatement(newstatement,cifnode.create(
  316. caddnode.create(equaln,
  317. load_self_pointer_node,
  318. cnilnode.create),
  319. cexitnode.create(nil),
  320. nil));
  321. end;
  322. { maybe call BeforeDestruction for classes }
  323. if (current_procinfo.procdef.proctypeoption=potype_destructor) and
  324. is_class(current_procinfo.procdef._class) then
  325. begin
  326. srsym:=search_class_member(current_procinfo.procdef._class,'BEFOREDESTRUCTION');
  327. if assigned(srsym) and
  328. (srsym.typ=procsym) then
  329. begin
  330. { if vmt<>0 then beforedestruction }
  331. addstatement(newstatement,cifnode.create(
  332. caddnode.create(unequaln,
  333. load_vmt_pointer_node,
  334. cnilnode.create),
  335. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
  336. nil));
  337. end
  338. else
  339. internalerror(200305104);
  340. end;
  341. end;
  342. end;
  343. function generate_bodyexit_block:tnode;
  344. var
  345. srsym : tsym;
  346. para : tcallparanode;
  347. newstatement : tstatementnode;
  348. begin
  349. result:=internalstatements(newstatement);
  350. if assigned(current_procinfo.procdef._class) then
  351. begin
  352. { maybe call AfterConstruction for classes }
  353. if (current_procinfo.procdef.proctypeoption=potype_constructor) and
  354. is_class(current_procinfo.procdef._class) then
  355. begin
  356. srsym:=search_class_member(current_procinfo.procdef._class,'AFTERCONSTRUCTION');
  357. if assigned(srsym) and
  358. (srsym.typ=procsym) then
  359. begin
  360. { Self can be nil when fail is called }
  361. { if self<>nil and vmt<>nil then afterconstruction }
  362. addstatement(newstatement,cifnode.create(
  363. caddnode.create(andn,
  364. caddnode.create(unequaln,
  365. load_self_pointer_node,
  366. cnilnode.create),
  367. caddnode.create(unequaln,
  368. load_vmt_pointer_node,
  369. cnilnode.create)),
  370. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
  371. nil));
  372. end
  373. else
  374. internalerror(200305106);
  375. end;
  376. { a destructor needs a help procedure }
  377. if (current_procinfo.procdef.proctypeoption=potype_destructor) then
  378. begin
  379. if is_class(current_procinfo.procdef._class) then
  380. begin
  381. srsym:=search_class_member(current_procinfo.procdef._class,'FREEINSTANCE');
  382. if assigned(srsym) and
  383. (srsym.typ=procsym) then
  384. begin
  385. { if self<>0 and vmt=1 then freeinstance }
  386. addstatement(newstatement,cifnode.create(
  387. caddnode.create(andn,
  388. caddnode.create(unequaln,
  389. load_self_pointer_node,
  390. cnilnode.create),
  391. caddnode.create(equaln,
  392. ctypeconvnode.create(
  393. load_vmt_pointer_node,
  394. voidpointertype),
  395. cpointerconstnode.create(1,voidpointertype))),
  396. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
  397. nil));
  398. end
  399. else
  400. internalerror(200305108);
  401. end
  402. else
  403. if is_object(current_procinfo.procdef._class) then
  404. begin
  405. { finalize object data }
  406. if current_procinfo.procdef._class.needs_inittable then
  407. addstatement(newstatement,finalize_data_node(load_self_node));
  408. { parameter 3 : vmt_offset }
  409. { parameter 2 : pointer to vmt }
  410. { parameter 1 : self pointer }
  411. para:=ccallparanode.create(
  412. cordconstnode.create(current_procinfo.procdef._class.vmt_offset,s32inttype,false),
  413. ccallparanode.create(
  414. ctypeconvnode.create_explicit(
  415. load_vmt_pointer_node,
  416. voidpointertype),
  417. ccallparanode.create(
  418. ctypeconvnode.create_explicit(
  419. load_self_pointer_node,
  420. voidpointertype),
  421. nil)));
  422. addstatement(newstatement,
  423. ccallnode.createintern('fpc_help_destructor',para));
  424. end
  425. else
  426. internalerror(200305105);
  427. end;
  428. end;
  429. end;
  430. function generate_except_block:tnode;
  431. var
  432. pd : tprocdef;
  433. newstatement : tstatementnode;
  434. dummycall : tcallnode;
  435. begin
  436. generate_except_block:=internalstatements(newstatement);
  437. { a constructor needs call destructor (if available) when it
  438. is not inherited }
  439. if assigned(current_procinfo.procdef._class) and
  440. (current_procinfo.procdef.proctypeoption=potype_constructor) then
  441. begin
  442. pd:=current_procinfo.procdef._class.searchdestructor;
  443. if assigned(pd) then
  444. begin
  445. { if vmt<>0 then call destructor }
  446. addstatement(newstatement,cifnode.create(
  447. caddnode.create(unequaln,
  448. load_vmt_pointer_node,
  449. cnilnode.create),
  450. ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node,[]),
  451. nil));
  452. end;
  453. end
  454. else
  455. begin
  456. { no constructor }
  457. { must be the return value finalized before reraising the exception? }
  458. if (not is_void(current_procinfo.procdef.rettype.def)) and
  459. (current_procinfo.procdef.rettype.def.needs_inittable) and
  460. (not is_class(current_procinfo.procdef.rettype.def)) then
  461. addstatement(newstatement,finalize_data_node(load_result_node));
  462. end;
  463. end;
  464. {****************************************************************************
  465. TCGProcInfo
  466. ****************************************************************************}
  467. constructor tcgprocinfo.create(aparent:tprocinfo);
  468. begin
  469. inherited Create(aparent);
  470. nestedprocs:=tlinkedlist.create;
  471. end;
  472. destructor tcgprocinfo.destroy;
  473. begin
  474. nestedprocs.free;
  475. if assigned(code) then
  476. code.free;
  477. inherited destroy;
  478. end;
  479. procedure tcgprocinfo.add_entry_exit_code;
  480. var
  481. finalcode,
  482. bodyentrycode,
  483. bodyexitcode,
  484. exceptcode : tnode;
  485. newblock : tblocknode;
  486. codestatement,
  487. newstatement : tstatementnode;
  488. oldfilepos : tfileposinfo;
  489. begin
  490. oldfilepos:=aktfilepos;
  491. { Generate code/locations used at start of proc }
  492. aktfilepos:=entrypos;
  493. entry_asmnode:=casmnode.create_get_position;
  494. loadpara_asmnode:=casmnode.create_get_position;
  495. init_asmnode:=casmnode.create_get_position;
  496. bodyentrycode:=generate_bodyentry_block;
  497. { Generate code/locations used at end of proc }
  498. aktfilepos:=exitpos;
  499. exitlabel_asmnode:=casmnode.create_get_position;
  500. final_asmnode:=casmnode.create_get_position;
  501. bodyexitcode:=generate_bodyexit_block;
  502. { Generate procedure by combining init+body+final,
  503. depending on the implicit finally we need to add
  504. an try...finally...end wrapper }
  505. newblock:=internalstatements(newstatement);
  506. if (cs_implicit_exceptions in aktmoduleswitches) and
  507. (pi_needs_implicit_finally in flags) and
  508. { but it's useless in init/final code of units }
  509. not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
  510. begin
  511. { Generate special exception block only needed when
  512. implicit finaly is used }
  513. aktfilepos:=exitpos;
  514. exceptcode:=generate_except_block;
  515. { Generate code that will be in the try...finally }
  516. finalcode:=internalstatements(codestatement);
  517. addstatement(codestatement,bodyexitcode);
  518. addstatement(codestatement,final_asmnode);
  519. { Initialize before try...finally...end frame }
  520. addstatement(newstatement,loadpara_asmnode);
  521. addstatement(newstatement,entry_asmnode);
  522. addstatement(newstatement,init_asmnode);
  523. addstatement(newstatement,bodyentrycode);
  524. aktfilepos:=entrypos;
  525. addstatement(newstatement,ctryfinallynode.create_implicit(
  526. code,
  527. finalcode,
  528. exceptcode));
  529. addstatement(newstatement,exitlabel_asmnode);
  530. { set flag the implicit finally has been generated }
  531. include(flags,pi_has_implicit_finally);
  532. end
  533. else
  534. begin
  535. addstatement(newstatement,loadpara_asmnode);
  536. addstatement(newstatement,entry_asmnode);
  537. addstatement(newstatement,init_asmnode);
  538. addstatement(newstatement,bodyentrycode);
  539. addstatement(newstatement,code);
  540. addstatement(newstatement,exitlabel_asmnode);
  541. addstatement(newstatement,bodyexitcode);
  542. addstatement(newstatement,final_asmnode);
  543. end;
  544. do_firstpass(newblock);
  545. code:=newblock;
  546. aktfilepos:=oldfilepos;
  547. end;
  548. procedure clearrefs(p : tnamedindexitem;arg:pointer);
  549. begin
  550. if (tsym(p).typ=varsym) then
  551. if tvarsym(p).refs>1 then
  552. tvarsym(p).refs:=1;
  553. end;
  554. procedure tcgprocinfo.generate_code;
  555. var
  556. oldprocinfo : tprocinfo;
  557. oldaktmaxfpuregisters : longint;
  558. oldfilepos : tfileposinfo;
  559. templist : Taasmoutput;
  560. headertai : tai;
  561. begin
  562. { the initialization procedure can be empty, then we
  563. don't need to generate anything. When it was an empty
  564. procedure there would be at least a blocknode }
  565. if not assigned(code) then
  566. exit;
  567. { We need valid code }
  568. if Errorcount<>0 then
  569. exit;
  570. { The RA and Tempgen shall not be available yet }
  571. if assigned(tg) then
  572. internalerror(200309201);
  573. oldprocinfo:=current_procinfo;
  574. oldfilepos:=aktfilepos;
  575. oldaktmaxfpuregisters:=aktmaxfpuregisters;
  576. current_procinfo:=self;
  577. aktfilepos:=entrypos;
  578. { get new labels }
  579. aktbreaklabel:=nil;
  580. aktcontinuelabel:=nil;
  581. templist:=Taasmoutput.create;
  582. { add parast/localst to symtablestack }
  583. add_to_symtablestack;
  584. { when size optimization only count occurrence }
  585. if cs_littlesize in aktglobalswitches then
  586. cg.t_times:=1
  587. else
  588. { reference for repetition is 100 }
  589. cg.t_times:=100;
  590. { clear register count }
  591. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
  592. symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
  593. { there's always a call to FPC_INITIALIZEUNITS/FPC_DO_EXIT in the main program }
  594. if (procdef.localst.symtablelevel=main_program_level) and
  595. (not current_module.is_unit) then
  596. include(flags,pi_do_call);
  597. { set implicit_finally flag when there are locals/paras to be finalized }
  598. current_procinfo.procdef.parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_finalize_paras,nil);
  599. current_procinfo.procdef.localst.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_finalize_locals,nil);
  600. { firstpass everything }
  601. flowcontrol:=[];
  602. do_firstpass(code);
  603. if code.registersfpu>0 then
  604. include(current_procinfo.flags,pi_uses_fpu);
  605. { add implicit entry and exit code }
  606. add_entry_exit_code;
  607. { only do secondpass if there are no errors }
  608. if ErrorCount=0 then
  609. begin
  610. { set the start offset to the start of the temp area in the stack }
  611. tg:=ttgobj.create;
  612. { Create register allocator }
  613. cg.init_register_allocators;
  614. set_first_temp_offset;
  615. generate_parameter_info;
  616. { Allocate space in temp/registers for parast and localst }
  617. aktfilepos:=entrypos;
  618. gen_alloc_parast(aktproccode,tparasymtable(procdef.parast));
  619. if procdef.localst.symtabletype=localsymtable then
  620. gen_alloc_localst(aktproccode,tlocalsymtable(procdef.localst));
  621. { Store temp offset for information about 'real' temps }
  622. tempstart:=tg.lasttemp;
  623. { Generate code to load register parameters in temps and insert local
  624. copies for values parameters. This must be done before the code for the
  625. body is generated because the localloc is updated.
  626. Note: The generated code will be inserted after the code generation of
  627. the body is finished, because only then the position is known }
  628. {$ifdef oldregvars}
  629. assign_regvars(code);
  630. {$endif oldreg}
  631. aktfilepos:=entrypos;
  632. gen_load_para_value(templist);
  633. { caller paraloc info is also necessary in the stackframe_entry
  634. code of the ppc (and possibly other processors) }
  635. if not procdef.has_paraloc_info then
  636. begin
  637. procdef.requiredargarea:=paramanager.create_paraloc_info(procdef,callerside);
  638. procdef.has_paraloc_info:=true;
  639. end;
  640. { generate code for the node tree }
  641. do_secondpass(code);
  642. aktproccode.concatlist(exprasmlist);
  643. {$ifdef i386}
  644. procdef.fpu_used:=code.registersfpu;
  645. {$endif i386}
  646. { The position of the loadpara_asmnode is now known }
  647. aktproccode.insertlistafter(loadpara_asmnode.currenttai,templist);
  648. { first generate entry and initialize code with the correct
  649. position and switches }
  650. aktfilepos:=entrypos;
  651. aktlocalswitches:=entryswitches;
  652. gen_entry_code(templist);
  653. aktproccode.insertlistafter(entry_asmnode.currenttai,templist);
  654. gen_initialize_code(templist,false);
  655. aktproccode.insertlistafter(init_asmnode.currenttai,templist);
  656. { now generate finalize and exit code with the correct position
  657. and switches }
  658. aktfilepos:=exitpos;
  659. aktlocalswitches:=exitswitches;
  660. gen_finalize_code(templist,false);
  661. { the finalcode must be concated if there was no position available,
  662. using insertlistafter will result in an insert at the start
  663. when currentai=nil }
  664. if assigned(final_asmnode.currenttai) then
  665. aktproccode.insertlistafter(final_asmnode.currenttai,templist)
  666. else
  667. aktproccode.concatlist(templist);
  668. { insert exit label at the correct position }
  669. cg.a_label(templist,aktexitlabel);
  670. if assigned(exitlabel_asmnode.currenttai) then
  671. aktproccode.insertlistafter(exitlabel_asmnode.currenttai,templist)
  672. else
  673. aktproccode.concatlist(templist);
  674. { exit code }
  675. gen_exit_code(templist);
  676. aktproccode.concatlist(templist);
  677. {$ifdef OLDREGVARS}
  678. { note: this must be done only after as much code as possible has }
  679. { been generated. The result is that when you ungetregister() a }
  680. { regvar, it will actually free the regvar (and alse free the }
  681. { the regvars at the same time). Doing this too early will }
  682. { confuse the register allocator, as the regvars will still be }
  683. { used. It should be done before loading the result regs (so }
  684. { they don't conflict with the regvars) and before }
  685. { gen_entry_code (that one has to be able to allocate the }
  686. { regvars again) (JM) }
  687. free_regvars(aktproccode);
  688. {$endif OLDREGVARS}
  689. { add code that will load the return value, this is not done
  690. for assembler routines when they didn't reference the result
  691. variable }
  692. gen_load_return_value(templist);
  693. aktproccode.concatlist(templist);
  694. { generate symbol and save end of header position }
  695. aktfilepos:=entrypos;
  696. gen_proc_symbol(templist);
  697. headertai:=tai(templist.last);
  698. { insert symbol }
  699. aktproccode.insertlist(templist);
  700. { Free space in temp/registers for parast and localst, must be
  701. done after gen_entry_code }
  702. aktfilepos:=exitpos;
  703. if procdef.localst.symtabletype=localsymtable then
  704. gen_free_localst(aktproccode,tlocalsymtable(procdef.localst));
  705. gen_free_parast(aktproccode,tparasymtable(procdef.parast));
  706. { The procedure body is finished, we can now
  707. allocate the registers }
  708. cg.do_register_allocation(aktproccode,headertai);
  709. { Add save and restore of used registers }
  710. aktfilepos:=entrypos;
  711. gen_save_used_regs(templist);
  712. aktproccode.insertlistafter(headertai,templist);
  713. aktfilepos:=exitpos;
  714. gen_restore_used_regs(aktproccode,procdef.funcret_paraloc[calleeside]);
  715. { Add entry code (stack allocation) after header }
  716. aktfilepos:=entrypos;
  717. gen_proc_entry_code(templist);
  718. aktproccode.insertlistafter(headertai,templist);
  719. { Add exit code at the end }
  720. aktfilepos:=exitpos;
  721. gen_proc_exit_code(templist);
  722. aktproccode.concatlist(templist);
  723. { check if the implicit finally has been generated. The flag
  724. should already be set in pass1 }
  725. if (cs_implicit_exceptions in aktmoduleswitches) and
  726. not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) and
  727. (pi_needs_implicit_finally in flags) and
  728. not(pi_has_implicit_finally in flags) then
  729. internalerror(200405231);
  730. {$ifndef NoOpt}
  731. if not(cs_no_regalloc in aktglobalswitches) then
  732. begin
  733. if (cs_optimize in aktglobalswitches) and
  734. { do not optimize pure assembler procedures }
  735. not(pi_is_assembler in flags) then
  736. optimize(aktproccode);
  737. end;
  738. {$endif NoOpt}
  739. { Add end symbol and debug info }
  740. aktfilepos:=exitpos;
  741. gen_proc_symbol_end(templist);
  742. aktproccode.concatlist(templist);
  743. {$ifdef ARM}
  744. insertpcrelativedata(aktproccode,aktlocaldata);
  745. {$endif ARM}
  746. { save local data (casetable) also in the same file }
  747. if assigned(aktlocaldata) and
  748. (not aktlocaldata.empty) then
  749. begin
  750. { because of the limited constant size of the arm, all data access is done pc relative }
  751. if target_info.cpu=cpu_arm then
  752. aktproccode.concatlist(aktlocaldata)
  753. else
  754. begin
  755. new_section(aktproccode,sec_data,lower(procdef.mangledname),0);
  756. aktproccode.concatlist(aktlocaldata);
  757. end;
  758. end;
  759. { add the procedure to the codesegment }
  760. maybe_new_object_file(codesegment);
  761. new_section(codesegment,sec_code,lower(procdef.mangledname),aktalignment.procalign);
  762. codesegment.concatlist(aktproccode);
  763. { only now we can remove the temps }
  764. tg.resettempgen;
  765. { stop tempgen and ra }
  766. tg.free;
  767. cg.done_register_allocators;
  768. tg:=nil;
  769. end;
  770. { restore symtablestack }
  771. remove_from_symtablestack;
  772. { restore }
  773. templist.free;
  774. aktmaxfpuregisters:=oldaktmaxfpuregisters;
  775. aktfilepos:=oldfilepos;
  776. current_procinfo:=oldprocinfo;
  777. end;
  778. procedure tcgprocinfo.add_to_symtablestack;
  779. var
  780. _class,hp : tobjectdef;
  781. begin
  782. { insert symtables for the class, but only if it is no nested function }
  783. if assigned(procdef._class) and
  784. not(assigned(parent) and
  785. assigned(parent.procdef) and
  786. assigned(parent.procdef._class)) then
  787. begin
  788. { insert them in the reverse order }
  789. hp:=nil;
  790. repeat
  791. _class:=procdef._class;
  792. while _class.childof<>hp do
  793. _class:=_class.childof;
  794. hp:=_class;
  795. _class.symtable.next:=symtablestack;
  796. symtablestack:=_class.symtable;
  797. until hp=procdef._class;
  798. end;
  799. { insert parasymtable in symtablestack when parsing
  800. a function }
  801. if procdef.parast.symtablelevel>=normal_function_level then
  802. begin
  803. procdef.parast.next:=symtablestack;
  804. symtablestack:=procdef.parast;
  805. end;
  806. procdef.localst.next:=symtablestack;
  807. symtablestack:=procdef.localst;
  808. end;
  809. procedure tcgprocinfo.remove_from_symtablestack;
  810. begin
  811. { remove localst/parast }
  812. if procdef.parast.symtablelevel>=normal_function_level then
  813. symtablestack:=symtablestack.next.next
  814. else
  815. symtablestack:=symtablestack.next;
  816. { remove class member symbol tables }
  817. while symtablestack.symtabletype=objectsymtable do
  818. symtablestack:=symtablestack.next;
  819. end;
  820. procedure tcgprocinfo.resetprocdef;
  821. begin
  822. { the local symtables can be deleted, but the parast }
  823. { doesn't, (checking definitons when calling a }
  824. { function }
  825. { not for a inline procedure !! (PM) }
  826. { at lexlevel = 1 localst is the staticsymtable itself }
  827. { so no dispose here !! }
  828. { The localst is also needed for debuginfo }
  829. if assigned(code) and
  830. not(cs_debuginfo in aktmoduleswitches) and
  831. not(cs_browser in aktmoduleswitches) and
  832. (procdef.proccalloption<>pocall_inline) then
  833. begin
  834. if procdef.parast.symtablelevel>=normal_function_level then
  835. procdef.localst.free;
  836. procdef.localst:=nil;
  837. end;
  838. { remove code tree, if not inline procedure }
  839. if assigned(code) then
  840. begin
  841. { the inline procedure has already got a copy of the tree
  842. stored in current_procinfo.procdef.code }
  843. code.free;
  844. code:=nil;
  845. if (procdef.proccalloption<>pocall_inline) then
  846. procdef.inlininginfo^.code:=nil;
  847. end;
  848. end;
  849. function containsforbiddennode(var n: tnode; arg: pointer): foreachnoderesult;
  850. begin
  851. if (n.nodetype <> exitn) then
  852. result := fen_false
  853. else
  854. result := fen_norecurse_true;
  855. end;
  856. function checknodeinlining(procdef: tprocdef): boolean;
  857. var
  858. paraitem: tparaitem;
  859. begin
  860. result := false;
  861. if not assigned(procdef.inlininginfo^.code) or
  862. (po_assembler in procdef.procoptions) or
  863. { no locals }
  864. (tprocdef(procdef).localst.symsearch.count <> 0) or
  865. { procedure, not function }
  866. (not is_void(procdef.rettype.def)) then
  867. exit;
  868. paraitem:=tparaitem(procdef.para.first);
  869. { all call by reference parameters, or parameters which don't }
  870. { get a new value? }
  871. { also note: in theory, if there are only value parameters and none of those }
  872. { are changed, we could also inline the paras. However, the compiler does }
  873. { not distinguish between "used but not changed" and "used and changed" }
  874. { (both are represented by vs_used), so that this not yet possible to do }
  875. while assigned(paraitem) do
  876. begin
  877. { we can't handle formaldefs, valuepara's which get a new value and special arrays }
  878. if ((paraitem.paratyp in [vs_out,vs_var]) and
  879. (paraitem.paratype.def.deftype=formaldef)) or
  880. is_special_array(paraitem.paratype.def) then
  881. exit;
  882. paraitem := tparaitem(paraitem.next);
  883. end;
  884. { we currently can't handle exit-statements (would exit the caller) }
  885. result := not foreachnodestatic(procdef.inlininginfo^.code,{$ifdef FPCPROCVAR}@{$endif}containsforbiddennode,nil);
  886. end;
  887. procedure tcgprocinfo.parse_body;
  888. var
  889. oldprocinfo : tprocinfo;
  890. oldblock_type : tblock_type;
  891. begin
  892. oldprocinfo:=current_procinfo;
  893. oldblock_type:=block_type;
  894. { reset break and continue labels }
  895. block_type:=bt_body;
  896. current_procinfo:=self;
  897. { calculate the lexical level }
  898. if procdef.parast.symtablelevel>maxnesting then
  899. Message(parser_e_too_much_lexlevel);
  900. { static is also important for local procedures !! }
  901. if (po_staticmethod in procdef.procoptions) then
  902. allow_only_static:=true
  903. else if (procdef.parast.symtablelevel=normal_function_level) then
  904. allow_only_static:=false;
  905. {$ifdef state_tracking}
  906. { aktstate:=Tstate_storage.create;}
  907. {$endif state_tracking}
  908. { create a local symbol table for this routine }
  909. if not assigned(procdef.localst) then
  910. procdef.insert_localst;
  911. { add parast/localst to symtablestack }
  912. add_to_symtablestack;
  913. { constant symbols are inserted in this symboltable }
  914. constsymtable:=symtablestack;
  915. { save entry info }
  916. entrypos:=aktfilepos;
  917. entryswitches:=aktlocalswitches;
  918. { parse the code ... }
  919. code:=block(current_module.islibrary);
  920. { save exit info }
  921. exitswitches:=aktlocalswitches;
  922. exitpos:=last_endtoken_filepos;
  923. { the procedure is now defined }
  924. procdef.forwarddef:=false;
  925. if assigned(code) then
  926. begin
  927. { get a better entry point }
  928. entrypos:=code.fileinfo;
  929. { Finish type checking pass }
  930. do_resulttypepass(code);
  931. end;
  932. { Check for unused labels, forwards, symbols for procedures. Static
  933. symtable is checked in pmodules.
  934. The check must be done after the resulttypepass }
  935. if (Errorcount=0) and
  936. (tstoredsymtable(procdef.localst).symtabletype<>staticsymtable) then
  937. begin
  938. { check if forwards are resolved }
  939. tstoredsymtable(procdef.localst).check_forwards;
  940. { check if all labels are used }
  941. tstoredsymtable(procdef.localst).checklabels;
  942. { remove cross unit overloads }
  943. tstoredsymtable(procdef.localst).unchain_overloaded;
  944. { check for unused symbols, but only if there is no asm block }
  945. if not(pi_uses_asm in flags) then
  946. begin
  947. tstoredsymtable(procdef.localst).allsymbolsused;
  948. tstoredsymtable(procdef.parast).allsymbolsused;
  949. end;
  950. end;
  951. { store a copy of the original tree for inline, for
  952. normal procedures only store a reference to the
  953. current tree }
  954. if (procdef.proccalloption=pocall_inline) then
  955. begin
  956. procdef.inlininginfo^.code:=code.getcopy;
  957. procdef.inlininginfo^.flags:=current_procinfo.flags;
  958. procdef.inlininginfo^.inlinenode:=checknodeinlining(procdef);
  959. end
  960. else
  961. procdef.inlininginfo^.code:=code;
  962. { Print the node to tree.log }
  963. if paraprintnodetree=1 then
  964. printnode_procdef(procdef);
  965. { ... remove symbol tables }
  966. remove_from_symtablestack;
  967. {$ifdef state_tracking}
  968. { aktstate.destroy;}
  969. {$endif state_tracking}
  970. { reset to normal non static function }
  971. if (procdef.parast.symtablelevel=normal_function_level) then
  972. allow_only_static:=false;
  973. current_procinfo:=oldprocinfo;
  974. block_type:=oldblock_type;
  975. end;
  976. {****************************************************************************
  977. PROCEDURE/FUNCTION PARSING
  978. ****************************************************************************}
  979. procedure check_init_paras(p:tnamedindexitem;arg:pointer);
  980. begin
  981. if tsym(p).typ<>varsym then
  982. exit;
  983. with tvarsym(p) do
  984. if (not is_class(vartype.def) and
  985. vartype.def.needs_inittable and
  986. (varspez in [vs_value,vs_out])) then
  987. include(current_procinfo.flags,pi_do_call);
  988. end;
  989. procedure read_proc;
  990. {
  991. Parses the procedure directives, then parses the procedure body, then
  992. generates the code for it
  993. }
  994. procedure do_generate_code(pi:tcgprocinfo);
  995. var
  996. hpi : tcgprocinfo;
  997. begin
  998. { generate code for this procedure }
  999. pi.generate_code;
  1000. { process nested procs }
  1001. hpi:=tcgprocinfo(pi.nestedprocs.first);
  1002. while assigned(hpi) do
  1003. begin
  1004. do_generate_code(hpi);
  1005. hpi:=tcgprocinfo(hpi.next);
  1006. end;
  1007. pi.resetprocdef;
  1008. end;
  1009. var
  1010. old_current_procinfo : tprocinfo;
  1011. oldconstsymtable : tsymtable;
  1012. oldfailtokenmode : tmodeswitch;
  1013. pdflags : tpdflags;
  1014. pd : tprocdef;
  1015. isnestedproc : boolean;
  1016. begin
  1017. { save old state }
  1018. oldconstsymtable:=constsymtable;
  1019. old_current_procinfo:=current_procinfo;
  1020. { reset current_procinfo.procdef to nil to be sure that nothing is writing
  1021. to an other procdef }
  1022. current_procinfo:=nil;
  1023. { parse procedure declaration }
  1024. if assigned(old_current_procinfo) and
  1025. assigned(old_current_procinfo.procdef) then
  1026. pd:=parse_proc_dec(old_current_procinfo.procdef._class)
  1027. else
  1028. pd:=parse_proc_dec(nil);
  1029. { set the default function options }
  1030. if parse_only then
  1031. begin
  1032. pd.forwarddef:=true;
  1033. { set also the interface flag, for better error message when the
  1034. implementation doesn't much this header }
  1035. pd.interfacedef:=true;
  1036. include(pd.procoptions,po_public);
  1037. pdflags:=[pd_interface];
  1038. end
  1039. else
  1040. begin
  1041. pdflags:=[pd_body];
  1042. if (not current_module.in_interface) then
  1043. include(pdflags,pd_implemen);
  1044. if (not current_module.is_unit) or
  1045. maybe_smartlink_symbol then
  1046. include(pd.procoptions,po_public);
  1047. pd.forwarddef:=false;
  1048. end;
  1049. { parse the directives that may follow }
  1050. parse_proc_directives(pd,pdflags);
  1051. { hint directives, these can be separated by semicolons here,
  1052. that needs to be handled here with a loop (PFV) }
  1053. while try_consume_hintdirective(pd.symoptions) do
  1054. Consume(_SEMICOLON);
  1055. { Set calling convention }
  1056. handle_calling_convention(pd);
  1057. { everything of the proc definition is known, we can now
  1058. calculate the parameters }
  1059. calc_parast(pd);
  1060. { search for forward declarations }
  1061. if not proc_add_definition(pd) then
  1062. begin
  1063. { A method must be forward defined (in the object declaration) }
  1064. if assigned(pd._class) and
  1065. (not assigned(old_current_procinfo.procdef._class)) then
  1066. begin
  1067. MessagePos1(pd.fileinfo,parser_e_header_dont_match_any_member,pd.fullprocname(false));
  1068. tprocsym(pd.procsym).write_parameter_lists(pd);
  1069. end
  1070. else
  1071. begin
  1072. { Give a better error if there is a forward def in the interface and only
  1073. a single implementation }
  1074. if (not pd.forwarddef) and
  1075. (not pd.interfacedef) and
  1076. (tprocsym(pd.procsym).procdef_count>1) and
  1077. tprocsym(pd.procsym).first_procdef.forwarddef and
  1078. tprocsym(pd.procsym).first_procdef.interfacedef and
  1079. not(tprocsym(pd.procsym).procdef_count>2) then
  1080. begin
  1081. MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
  1082. tprocsym(pd.procsym).write_parameter_lists(pd);
  1083. end;
  1084. end;
  1085. end;
  1086. { compile procedure when a body is needed }
  1087. if (pd_body in pdflags) then
  1088. begin
  1089. Message1(parser_d_procedure_start,pd.fullprocname(false));
  1090. { create a new procedure }
  1091. current_procinfo:=cprocinfo.create(old_current_procinfo);
  1092. current_module.procinfo:=current_procinfo;
  1093. current_procinfo.procdef:=pd;
  1094. isnestedproc:=(current_procinfo.procdef.parast.symtablelevel>normal_function_level);
  1095. { Insert mangledname }
  1096. pd.aliasnames.insert(pd.mangledname);
  1097. { Insert result variables in the localst }
  1098. insert_funcret_local(pd);
  1099. { check if there are para's which require initing -> set }
  1100. { pi_do_call (if not yet set) }
  1101. if not(pi_do_call in current_procinfo.flags) then
  1102. pd.parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_init_paras,nil);
  1103. { set _FAIL as keyword if constructor }
  1104. if (pd.proctypeoption=potype_constructor) then
  1105. begin
  1106. oldfailtokenmode:=tokeninfo^[_FAIL].keyword;
  1107. tokeninfo^[_FAIL].keyword:=m_all;
  1108. end;
  1109. tcgprocinfo(current_procinfo).parse_body;
  1110. { When it's a nested procedure then defer the code generation,
  1111. when back at normal function level then generate the code
  1112. for all defered nested procedures and the current procedure }
  1113. if isnestedproc then
  1114. tcgprocinfo(current_procinfo.parent).nestedprocs.insert(current_procinfo)
  1115. else
  1116. begin
  1117. { We can't support inlining for procedures that have nested
  1118. procedures because the nested procedures use a fixed offset
  1119. for accessing locals in the parent procedure (PFV) }
  1120. if (current_procinfo.procdef.proccalloption=pocall_inline) and
  1121. (tcgprocinfo(current_procinfo).nestedprocs.count>0) then
  1122. begin
  1123. Message1(parser_w_not_supported_for_inline,'nested procedures');
  1124. Message(parser_w_inlining_disabled);
  1125. current_procinfo.procdef.proccalloption:=pocall_default;
  1126. end;
  1127. do_generate_code(tcgprocinfo(current_procinfo));
  1128. end;
  1129. { reset _FAIL as _SELF normal }
  1130. if (pd.proctypeoption=potype_constructor) then
  1131. tokeninfo^[_FAIL].keyword:=oldfailtokenmode;
  1132. { release procinfo }
  1133. if tprocinfo(current_module.procinfo)<>current_procinfo then
  1134. internalerror(200304274);
  1135. current_module.procinfo:=current_procinfo.parent;
  1136. if not isnestedproc then
  1137. current_procinfo.free;
  1138. consume(_SEMICOLON);
  1139. end;
  1140. { Restore old state }
  1141. constsymtable:=oldconstsymtable;
  1142. current_procinfo:=old_current_procinfo;
  1143. end;
  1144. {****************************************************************************
  1145. DECLARATION PARSING
  1146. ****************************************************************************}
  1147. { search in symtablestack for not complete classes }
  1148. procedure check_forward_class(p : tnamedindexitem;arg:pointer);
  1149. begin
  1150. if (tsym(p).typ=typesym) and
  1151. (ttypesym(p).restype.def.deftype=objectdef) and
  1152. (oo_is_forward in tobjectdef(ttypesym(p).restype.def).objectoptions) then
  1153. MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
  1154. end;
  1155. procedure read_declarations(islibrary : boolean);
  1156. begin
  1157. repeat
  1158. if not assigned(current_procinfo) then
  1159. internalerror(200304251);
  1160. case token of
  1161. _LABEL:
  1162. label_dec;
  1163. _CONST:
  1164. const_dec;
  1165. _TYPE:
  1166. type_dec;
  1167. _VAR:
  1168. var_dec;
  1169. _THREADVAR:
  1170. threadvar_dec;
  1171. _CONSTRUCTOR,
  1172. _DESTRUCTOR,
  1173. _FUNCTION,
  1174. _PROCEDURE,
  1175. _OPERATOR,
  1176. _CLASS:
  1177. read_proc;
  1178. _EXPORTS:
  1179. begin
  1180. if not(assigned(current_procinfo.procdef.localst)) or
  1181. (current_procinfo.procdef.localst.symtablelevel>main_program_level) or
  1182. (current_module.is_unit) then
  1183. begin
  1184. Message(parser_e_syntax_error);
  1185. consume_all_until(_SEMICOLON);
  1186. end
  1187. else if islibrary or
  1188. (target_info.system in [system_i386_WIN32,system_i386_wdosx,system_i386_Netware]) then
  1189. read_exports
  1190. else
  1191. begin
  1192. Message(parser_w_unsupported_feature);
  1193. consume(_BEGIN);
  1194. end;
  1195. end
  1196. else
  1197. begin
  1198. case idtoken of
  1199. _RESOURCESTRING :
  1200. resourcestring_dec;
  1201. _PROPERTY:
  1202. begin
  1203. if (m_fpc in aktmodeswitches) then
  1204. property_dec
  1205. else
  1206. break;
  1207. end;
  1208. else
  1209. break;
  1210. end;
  1211. end;
  1212. end;
  1213. until false;
  1214. { check for incomplete class definitions, this is only required
  1215. for fpc modes }
  1216. if (m_fpc in aktmodeswitches) then
  1217. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_forward_class,nil);
  1218. end;
  1219. procedure read_interface_declarations;
  1220. begin
  1221. repeat
  1222. case token of
  1223. _CONST :
  1224. const_dec;
  1225. _TYPE :
  1226. type_dec;
  1227. _VAR :
  1228. var_dec;
  1229. _THREADVAR :
  1230. threadvar_dec;
  1231. _FUNCTION,
  1232. _PROCEDURE,
  1233. _OPERATOR :
  1234. read_proc;
  1235. else
  1236. begin
  1237. case idtoken of
  1238. _RESOURCESTRING :
  1239. resourcestring_dec;
  1240. _PROPERTY:
  1241. begin
  1242. if (m_fpc in aktmodeswitches) then
  1243. property_dec
  1244. else
  1245. break;
  1246. end;
  1247. else
  1248. break;
  1249. end;
  1250. end;
  1251. end;
  1252. until false;
  1253. { check for incomplete class definitions, this is only required
  1254. for fpc modes }
  1255. if (m_fpc in aktmodeswitches) then
  1256. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_forward_class,nil);
  1257. end;
  1258. end.
  1259. {
  1260. $Log$
  1261. Revision 1.202 2004-07-16 21:11:31 jonas
  1262. - disable node-based inlining of routines with special array parameters
  1263. for now (de indexes of open arrays have to be changed, because on the
  1264. caller-side these routines are not necessarily 0-based)
  1265. Revision 1.201 2004/07/15 19:55:40 jonas
  1266. + (incomplete) node_complexity function to assess the complexity of a
  1267. tree
  1268. + support for inlining value and const parameters at the node level
  1269. (all procedures without local variables and without formal parameters
  1270. can now be inlined at the node level)
  1271. Revision 1.200 2004/07/12 09:14:04 jonas
  1272. * inline procedures at the node tree level, but only under some very
  1273. limited circumstances for now (only procedures, and only if they have
  1274. no or only vs_out/vs_var parameters).
  1275. * fixed ppudump for inline procedures
  1276. * fixed ppudump for ppc
  1277. Revision 1.199 2004/07/10 20:24:34 peter
  1278. * put every proc in a new object file
  1279. Revision 1.198 2004/07/09 22:17:32 peter
  1280. * revert has_localst patch
  1281. * replace aktstaticsymtable/aktglobalsymtable with current_module
  1282. Revision 1.197 2004/07/06 19:52:04 peter
  1283. * fix storing of localst in ppu
  1284. Revision 1.196 2004/06/20 08:55:30 florian
  1285. * logs truncated
  1286. Revision 1.195 2004/06/16 20:07:09 florian
  1287. * dwarf branch merged
  1288. Revision 1.194 2004/05/28 21:14:13 peter
  1289. * first load para's to temps before calling entry code (profile
  1290. Revision 1.193 2004/05/24 17:31:12 peter
  1291. * also check local typed const
  1292. Revision 1.192 2004/05/23 18:28:41 peter
  1293. * methodpointer is loaded into a temp when it was a calln
  1294. Revision 1.191 2004/05/23 15:06:21 peter
  1295. * implicit_finally flag must be set in pass1
  1296. * add check whether the implicit frame is generated when expected
  1297. }