psub.pas 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl, Daniel Mantione
  3. Does the parsing and codegeneration at subroutine level
  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 psub;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globals,
  22. node,nbas,
  23. symdef,procinfo,optdfa;
  24. type
  25. { tcgprocinfo }
  26. tcgprocinfo = class(tprocinfo)
  27. private
  28. procedure CreateInlineInfo;
  29. { returns the node which is the start of the user code, this is needed by the dfa }
  30. function GetUserCode: tnode;
  31. procedure maybe_add_constructor_wrapper(var tocode: tnode; withexceptblock: boolean);
  32. procedure add_entry_exit_code;
  33. procedure setup_tempgen;
  34. public
  35. { code for the subroutine as tree }
  36. code : tnode;
  37. { positions in the tree for init/final }
  38. entry_asmnode,
  39. loadpara_asmnode,
  40. exitlabel_asmnode,
  41. stackcheck_asmnode,
  42. init_asmnode,
  43. final_asmnode : tasmnode;
  44. final_used : boolean;
  45. dfabuilder : TDFABuilder;
  46. destructor destroy;override;
  47. procedure printproc(pass:string);
  48. procedure generate_code;
  49. procedure generate_code_tree;
  50. procedure generate_exceptfilter(nestedpi: tcgprocinfo);
  51. procedure resetprocdef;
  52. procedure add_to_symtablestack;
  53. procedure remove_from_symtablestack;
  54. procedure parse_body;
  55. function has_assembler_child : boolean;
  56. end;
  57. procedure printnode_reset;
  58. { reads the declaration blocks }
  59. procedure read_declarations(islibrary : boolean);
  60. { reads declarations in the interface part of a unit }
  61. procedure read_interface_declarations;
  62. { reads any routine in the implementation, or a non-method routine
  63. declaration in the interface (depending on whether or not parse_only is
  64. true) }
  65. procedure read_proc(isclassmethod:boolean; usefwpd: tprocdef);
  66. procedure generate_specialization_procs;
  67. implementation
  68. uses
  69. sysutils,
  70. { common }
  71. cutils,
  72. { global }
  73. globtype,tokens,verbose,comphook,constexp,
  74. systems,cpubase,aasmbase,aasmtai,aasmdata,
  75. { symtable }
  76. symconst,symbase,symsym,symtype,symtable,defutil,symcreat,
  77. paramgr,
  78. ppu,fmodule,
  79. { pass 1 }
  80. nutils,ngenutil,nld,ncal,ncon,nflw,nadd,ncnv,nmem,
  81. pass_1,
  82. {$ifdef state_tracking}
  83. nstate,
  84. {$endif state_tracking}
  85. { pass 2 }
  86. {$ifndef NOPASS2}
  87. pass_2,
  88. {$endif}
  89. { parser }
  90. scanner,gendef,
  91. pbase,pstatmnt,pdecl,pdecsub,pexports,pgenutil,pparautl,
  92. { codegen }
  93. tgobj,cgbase,cgobj,hlcgobj,hlcgcpu,dbgbase,
  94. {$ifdef llvm}
  95. { override create_hlcodegen from hlcgcpu }
  96. hlcgllvm,
  97. {$endif}
  98. ncgutil,regvars,
  99. optbase,
  100. opttail,
  101. optcse,
  102. optloop,
  103. optconstprop,
  104. optdeadstore
  105. {$if defined(arm) or defined(avr) or defined(fpc_compiler_has_fixup_jmps)}
  106. ,aasmcpu
  107. {$endif arm}
  108. {$if defined(arm)}
  109. ,cpuinfo
  110. {$endif arm}
  111. {$ifndef NOOPT}
  112. {$ifdef i386}
  113. ,aopt386
  114. {$else i386}
  115. ,aopt
  116. {$endif i386}
  117. {$endif}
  118. ;
  119. function checknodeinlining(procdef: tprocdef): boolean;
  120. var
  121. i : integer;
  122. currpara : tparavarsym;
  123. begin
  124. result := false;
  125. if pi_has_assembler_block in current_procinfo.flags then
  126. begin
  127. Message1(parser_h_not_supported_for_inline,'assembler');
  128. Message(parser_h_inlining_disabled);
  129. exit;
  130. end;
  131. if pi_has_global_goto in current_procinfo.flags then
  132. begin
  133. Message1(parser_h_not_supported_for_inline,'global goto');
  134. Message(parser_h_inlining_disabled);
  135. exit;
  136. end;
  137. if pi_has_nested_exit in current_procinfo.flags then
  138. begin
  139. Message1(parser_h_not_supported_for_inline,'nested exit');
  140. Message(parser_h_inlining_disabled);
  141. exit;
  142. end;
  143. { the compiler cannot handle inherited in inlined subroutines because
  144. it tries to search for self in the symtable, however, the symtable
  145. is not available }
  146. if pi_has_inherited in current_procinfo.flags then
  147. begin
  148. Message1(parser_h_not_supported_for_inline,'inherited');
  149. Message(parser_h_inlining_disabled);
  150. exit;
  151. end;
  152. for i:=0 to procdef.paras.count-1 do
  153. begin
  154. currpara:=tparavarsym(procdef.paras[i]);
  155. case currpara.vardef.typ of
  156. formaldef :
  157. begin
  158. if (currpara.varspez in [vs_out,vs_var,vs_const,vs_constref]) then
  159. begin
  160. Message1(parser_h_not_supported_for_inline,'formal parameter');
  161. Message(parser_h_inlining_disabled);
  162. exit;
  163. end;
  164. end;
  165. arraydef :
  166. begin
  167. if is_array_of_const(currpara.vardef) or
  168. is_variant_array(currpara.vardef) then
  169. begin
  170. Message1(parser_h_not_supported_for_inline,'array of const');
  171. Message(parser_h_inlining_disabled);
  172. exit;
  173. end;
  174. { open arrays might need re-basing of the index, i.e. if you pass
  175. an array[1..10] as open array, you have to add 1 to all index operations
  176. if you directly inline it }
  177. if is_open_array(currpara.vardef) then
  178. begin
  179. Message1(parser_h_not_supported_for_inline,'open array');
  180. Message(parser_h_inlining_disabled);
  181. exit;
  182. end;
  183. end;
  184. end;
  185. end;
  186. result:=true;
  187. end;
  188. {****************************************************************************
  189. PROCEDURE/FUNCTION BODY PARSING
  190. ****************************************************************************}
  191. procedure initializedefaultvars(p:TObject;arg:pointer);
  192. var
  193. b : tblocknode;
  194. begin
  195. if tsym(p).typ<>localvarsym then
  196. exit;
  197. with tabstractnormalvarsym(p) do
  198. begin
  199. if vo_is_default_var in varoptions then
  200. begin
  201. b:=tblocknode(arg);
  202. b.left:=cstatementnode.create(
  203. ccallnode.createintern('fpc_zeromem',
  204. ccallparanode.create(
  205. cordconstnode.create(vardef.size,ptruinttype,false),
  206. ccallparanode.create(
  207. caddrnode.create_internal(
  208. cloadnode.create(tsym(p),tsym(p).owner)),
  209. nil
  210. )
  211. )
  212. ),
  213. b.left);
  214. end;
  215. end;
  216. end;
  217. procedure initializevars(p:TObject;arg:pointer);
  218. var
  219. b : tblocknode;
  220. begin
  221. if not (tsym(p).typ in [localvarsym,staticvarsym]) then
  222. exit;
  223. with tabstractnormalvarsym(p) do
  224. begin
  225. if assigned(defaultconstsym) then
  226. begin
  227. b:=tblocknode(arg);
  228. b.left:=cstatementnode.create(
  229. cassignmentnode.create(
  230. cloadnode.create(tsym(p),tsym(p).owner),
  231. cloadnode.create(defaultconstsym,defaultconstsym.owner)),
  232. b.left);
  233. end
  234. else
  235. initializedefaultvars(p,arg);
  236. end;
  237. end;
  238. procedure check_finalize_paras(p:TObject;arg:pointer);
  239. begin
  240. if (tsym(p).typ=paravarsym) then
  241. begin
  242. if tparavarsym(p).needs_finalization then
  243. include(current_procinfo.flags,pi_needs_implicit_finally);
  244. if (tparavarsym(p).varspez in [vs_value,vs_out]) and
  245. (cs_create_pic in current_settings.moduleswitches) and
  246. (tf_pic_uses_got in target_info.flags) and
  247. is_rtti_managed_type(tparavarsym(p).vardef) then
  248. include(current_procinfo.flags,pi_needs_got);
  249. end;
  250. end;
  251. procedure check_finalize_locals(p:TObject;arg:pointer);
  252. begin
  253. { include the result: it needs to be finalized in case an exception }
  254. { occurs }
  255. if (tsym(p).typ=localvarsym) and
  256. (tlocalvarsym(p).refs>0) and
  257. is_managed_type(tlocalvarsym(p).vardef) then
  258. begin
  259. include(current_procinfo.flags,pi_needs_implicit_finally);
  260. if is_rtti_managed_type(tlocalvarsym(p).vardef) and
  261. (cs_create_pic in current_settings.moduleswitches) and
  262. (tf_pic_uses_got in target_info.flags) then
  263. include(current_procinfo.flags,pi_needs_got);
  264. end;
  265. end;
  266. function block(islibrary : boolean) : tnode;
  267. var
  268. oldfilepos: tfileposinfo;
  269. begin
  270. { parse const,types and vars }
  271. read_declarations(islibrary);
  272. { do we have an assembler block without the po_assembler?
  273. we should allow this for Delphi compatibility (PFV) }
  274. if (token=_ASM) and (m_delphi in current_settings.modeswitches) then
  275. include(current_procinfo.procdef.procoptions,po_assembler);
  276. { Handle assembler block different }
  277. if (po_assembler in current_procinfo.procdef.procoptions) then
  278. begin
  279. block:=assembler_block;
  280. exit;
  281. end;
  282. {Unit initialization?.}
  283. if (
  284. assigned(current_procinfo.procdef.localst) and
  285. (current_procinfo.procdef.localst.symtablelevel=main_program_level) and
  286. (current_module.is_unit or islibrary)
  287. ) then
  288. begin
  289. if (token=_END) then
  290. begin
  291. consume(_END);
  292. { We need at least a node, else the entry/exit code is not
  293. generated and thus no PASCALMAIN symbol which we need (PFV) }
  294. if islibrary then
  295. block:=cnothingnode.create
  296. else
  297. block:=nil;
  298. end
  299. else
  300. begin
  301. if token=_INITIALIZATION then
  302. begin
  303. { The library init code is already called and does not
  304. need to be in the initfinal table (PFV) }
  305. block:=statement_block(_INITIALIZATION);
  306. end
  307. else if token=_FINALIZATION then
  308. begin
  309. { when a unit has only a finalization section, we can come to this
  310. point when we try to read the nonh existing initalization section
  311. so we've to check if we are really try to parse the finalization }
  312. if current_procinfo.procdef.proctypeoption=potype_unitfinalize then
  313. block:=statement_block(_FINALIZATION)
  314. else
  315. block:=nil;
  316. end
  317. else
  318. block:=statement_block(_BEGIN);
  319. end;
  320. end
  321. else
  322. begin
  323. { parse routine body }
  324. block:=statement_block(_BEGIN);
  325. { initialized variables }
  326. if current_procinfo.procdef.localst.symtabletype=localsymtable then
  327. begin
  328. { initialization of local variables with their initial
  329. values: part of function entry }
  330. oldfilepos:=current_filepos;
  331. current_filepos:=current_procinfo.entrypos;
  332. current_procinfo.procdef.localst.SymList.ForEachCall(@initializevars,block);
  333. current_filepos:=oldfilepos;
  334. end
  335. else if current_procinfo.procdef.localst.symtabletype=staticsymtable then
  336. begin
  337. { for program and unit initialization code we also need to
  338. initialize the local variables used of Default() }
  339. oldfilepos:=current_filepos;
  340. current_filepos:=current_procinfo.entrypos;
  341. current_procinfo.procdef.localst.SymList.ForEachCall(@initializedefaultvars,block);
  342. current_filepos:=oldfilepos;
  343. end;
  344. if assigned(current_procinfo.procdef.parentfpstruct) then
  345. begin
  346. { we only do this after the code has been parsed because
  347. otherwise for-loop counters moved to the struct cause
  348. errors; we still do it nevertheless to prevent false
  349. "unused" symbols warnings and to assist debug info
  350. generation }
  351. redirect_parentfpstruct_local_syms(current_procinfo.procdef);
  352. { finish the parentfpstruct (add padding, ...) }
  353. finish_parentfpstruct(current_procinfo.procdef);
  354. end;
  355. end;
  356. end;
  357. {****************************************************************************
  358. PROCEDURE/FUNCTION COMPILING
  359. ****************************************************************************}
  360. procedure printnode_reset;
  361. begin
  362. assign(printnodefile,treelogfilename);
  363. {$push}{$I-}
  364. rewrite(printnodefile);
  365. {$pop}
  366. if ioresult<>0 then
  367. begin
  368. Comment(V_Error,'Error creating '+treelogfilename);
  369. exit;
  370. end;
  371. close(printnodefile);
  372. end;
  373. procedure add_label_init(p:TObject;arg:pointer);
  374. begin
  375. if tstoredsym(p).typ=labelsym then
  376. begin
  377. addstatement(tstatementnode(arg^),
  378. cifnode.create(caddnode.create(equaln,
  379. ccallnode.createintern('fpc_setjmp',
  380. ccallparanode.create(cloadnode.create(tlabelsym(p).jumpbuf,tlabelsym(p).jumpbuf.owner),nil)),
  381. cordconstnode.create(1,sinttype,true))
  382. ,cgotonode.create(tlabelsym(p)),nil)
  383. );
  384. end;
  385. end;
  386. function generate_bodyentry_block:tnode;
  387. var
  388. srsym : tsym;
  389. para : tcallparanode;
  390. call : tcallnode;
  391. newstatement : tstatementnode;
  392. def : tabstractrecorddef;
  393. begin
  394. result:=internalstatements(newstatement);
  395. if assigned(current_structdef) then
  396. begin
  397. { a constructor needs a help procedure }
  398. if (current_procinfo.procdef.proctypeoption=potype_constructor) then
  399. begin
  400. if is_class(current_structdef) or
  401. (
  402. is_objectpascal_helper(current_structdef) and
  403. is_class(tobjectdef(current_structdef).extendeddef)
  404. ) then
  405. begin
  406. if is_objectpascal_helper(current_structdef) then
  407. def:=tabstractrecorddef(tobjectdef(current_structdef).extendeddef)
  408. else
  409. def:=current_structdef;
  410. srsym:=search_struct_member(def,'NEWINSTANCE');
  411. if assigned(srsym) and
  412. (srsym.typ=procsym) then
  413. begin
  414. { if vmt>1 then newinstance }
  415. addstatement(newstatement,cifnode.create(
  416. caddnode.create_internal(gtn,
  417. ctypeconvnode.create_internal(
  418. load_vmt_pointer_node,
  419. voidpointertype),
  420. cpointerconstnode.create(1,voidpointertype)),
  421. cassignmentnode.create(
  422. ctypeconvnode.create_internal(
  423. load_self_pointer_node,
  424. voidpointertype),
  425. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node,[])),
  426. nil));
  427. end
  428. else
  429. internalerror(200305108);
  430. end
  431. else
  432. if is_object(current_structdef) then
  433. begin
  434. { parameter 3 : vmt_offset }
  435. { parameter 2 : address of pointer to vmt,
  436. this is required to allow setting the vmt to -1 to indicate
  437. that memory was allocated }
  438. { parameter 1 : self pointer }
  439. para:=ccallparanode.create(
  440. cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
  441. ccallparanode.create(
  442. ctypeconvnode.create_internal(
  443. load_vmt_pointer_node,
  444. voidpointertype),
  445. ccallparanode.create(
  446. ctypeconvnode.create_internal(
  447. load_self_pointer_node,
  448. voidpointertype),
  449. nil)));
  450. addstatement(newstatement,cassignmentnode.create(
  451. ctypeconvnode.create_internal(
  452. load_self_pointer_node,
  453. voidpointertype),
  454. ccallnode.createintern('fpc_help_constructor',para)));
  455. end
  456. else
  457. if is_javaclass(current_structdef) or
  458. ((target_info.system in systems_jvm) and
  459. is_record(current_structdef)) then
  460. begin
  461. if (current_procinfo.procdef.proctypeoption=potype_constructor) and
  462. not current_procinfo.ConstructorCallingConstructor then
  463. begin
  464. { call inherited constructor }
  465. if is_javaclass(current_structdef) then
  466. srsym:=search_struct_member_no_helper(tobjectdef(current_structdef).childof,'CREATE')
  467. else
  468. srsym:=search_struct_member_no_helper(java_fpcbaserecordtype,'CREATE');
  469. if assigned(srsym) and
  470. (srsym.typ=procsym) then
  471. begin
  472. call:=ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[cnf_inherited]);
  473. exclude(tcallnode(call).callnodeflags,cnf_return_value_used);
  474. addstatement(newstatement,call);
  475. end
  476. else
  477. internalerror(2011010312);
  478. end;
  479. end
  480. else
  481. if not is_record(current_structdef) and
  482. not (
  483. is_objectpascal_helper(current_structdef) and
  484. (tobjectdef(current_structdef).extendeddef.typ<>objectdef)
  485. ) then
  486. internalerror(200305103);
  487. { if self=nil then exit
  488. calling fail instead of exit is useless because
  489. there is nothing to dispose (PFV) }
  490. if is_class_or_object(current_structdef) then
  491. addstatement(newstatement,cifnode.create(
  492. caddnode.create(equaln,
  493. load_self_pointer_node,
  494. cnilnode.create),
  495. cexitnode.create(nil),
  496. nil));
  497. end;
  498. { maybe call BeforeDestruction for classes }
  499. if (current_procinfo.procdef.proctypeoption=potype_destructor) and
  500. is_class(current_structdef) then
  501. begin
  502. srsym:=search_struct_member(current_structdef,'BEFOREDESTRUCTION');
  503. if assigned(srsym) and
  504. (srsym.typ=procsym) then
  505. begin
  506. { if vmt>0 then beforedestruction }
  507. addstatement(newstatement,cifnode.create(
  508. caddnode.create(gtn,
  509. ctypeconvnode.create_internal(
  510. load_vmt_pointer_node,ptrsinttype),
  511. ctypeconvnode.create_internal(
  512. cnilnode.create,ptrsinttype)),
  513. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
  514. nil));
  515. end
  516. else
  517. internalerror(200305104);
  518. end;
  519. end;
  520. if m_non_local_goto in current_settings.modeswitches then
  521. tsymtable(current_procinfo.procdef.localst).SymList.ForEachCall(@add_label_init,@newstatement);
  522. end;
  523. function generate_bodyexit_block:tnode;
  524. var
  525. srsym : tsym;
  526. para : tcallparanode;
  527. newstatement : tstatementnode;
  528. oldlocalswitches: tlocalswitches;
  529. begin
  530. result:=internalstatements(newstatement);
  531. if assigned(current_structdef) then
  532. begin
  533. { Don't test self and the vmt here. The reason is that }
  534. { a constructor already checks whether these are valid }
  535. { before. Further, in case of TThread the thread may }
  536. { free the class instance right after AfterConstruction }
  537. { has been called, so it may no longer be valid (JM) }
  538. oldlocalswitches:=current_settings.localswitches;
  539. current_settings.localswitches:=oldlocalswitches-[cs_check_object,cs_check_range];
  540. { a destructor needs a help procedure }
  541. if (current_procinfo.procdef.proctypeoption=potype_destructor) then
  542. begin
  543. if is_class(current_structdef) then
  544. begin
  545. srsym:=search_struct_member(current_structdef,'FREEINSTANCE');
  546. if assigned(srsym) and
  547. (srsym.typ=procsym) then
  548. begin
  549. { if self<>0 and vmt<>0 then freeinstance }
  550. addstatement(newstatement,cifnode.create(
  551. caddnode.create(andn,
  552. caddnode.create(unequaln,
  553. load_self_pointer_node,
  554. cnilnode.create),
  555. caddnode.create(unequaln,
  556. ctypeconvnode.create(
  557. load_vmt_pointer_node,
  558. voidpointertype),
  559. cpointerconstnode.create(0,voidpointertype))),
  560. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
  561. nil));
  562. end
  563. else
  564. internalerror(200305108);
  565. end
  566. else
  567. if is_object(current_structdef) then
  568. begin
  569. { finalize object data, but only if not in inherited call }
  570. if is_managed_type(current_structdef) then
  571. begin
  572. addstatement(newstatement,cifnode.create(
  573. caddnode.create(unequaln,
  574. ctypeconvnode.create_internal(load_vmt_pointer_node,voidpointertype),
  575. cnilnode.create),
  576. cnodeutils.finalize_data_node(load_self_node),
  577. nil));
  578. end;
  579. { parameter 3 : vmt_offset }
  580. { parameter 2 : pointer to vmt }
  581. { parameter 1 : self pointer }
  582. para:=ccallparanode.create(
  583. cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
  584. ccallparanode.create(
  585. ctypeconvnode.create_internal(
  586. load_vmt_pointer_node,
  587. voidpointertype),
  588. ccallparanode.create(
  589. ctypeconvnode.create_internal(
  590. load_self_pointer_node,
  591. voidpointertype),
  592. nil)));
  593. addstatement(newstatement,
  594. ccallnode.createintern('fpc_help_destructor',para));
  595. end
  596. else if is_javaclass(current_structdef) then
  597. begin
  598. { nothing to do }
  599. end
  600. else
  601. internalerror(200305105);
  602. end;
  603. current_settings.localswitches:=oldlocalswitches;
  604. end;
  605. end;
  606. function generate_except_block:tnode;
  607. var
  608. newstatement : tstatementnode;
  609. begin
  610. generate_except_block:=internalstatements(newstatement);
  611. { a constructor needs call destructor (if available) when it
  612. is not inherited }
  613. if not assigned(current_structdef) or
  614. (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  615. begin
  616. { no constructor }
  617. { must be the return value finalized before reraising the exception? }
  618. if (not is_void(current_procinfo.procdef.returndef)) and
  619. is_managed_type(current_procinfo.procdef.returndef) and
  620. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) and
  621. (not is_class(current_procinfo.procdef.returndef)) then
  622. addstatement(newstatement,cnodeutils.finalize_data_node(load_result_node));
  623. end;
  624. end;
  625. {****************************************************************************
  626. TCGProcInfo
  627. ****************************************************************************}
  628. destructor tcgprocinfo.destroy;
  629. begin
  630. if assigned(code) then
  631. code.free;
  632. if not final_used then
  633. final_asmnode.free;
  634. inherited destroy;
  635. end;
  636. procedure tcgprocinfo.printproc(pass:string);
  637. begin
  638. assign(printnodefile,treelogfilename);
  639. {$push}{$I-}
  640. append(printnodefile);
  641. if ioresult<>0 then
  642. rewrite(printnodefile);
  643. {$pop}
  644. if ioresult<>0 then
  645. begin
  646. Comment(V_Error,'Error creating '+treelogfilename);
  647. exit;
  648. end;
  649. writeln(printnodefile);
  650. writeln(printnodefile,'*******************************************************************************');
  651. writeln(printnodefile, pass);
  652. writeln(printnodefile,procdef.fullprocname(false));
  653. writeln(printnodefile,'*******************************************************************************');
  654. printnode(printnodefile,code);
  655. close(printnodefile);
  656. end;
  657. procedure tcgprocinfo.maybe_add_constructor_wrapper(var tocode: tnode; withexceptblock: boolean);
  658. var
  659. oldlocalswitches: tlocalswitches;
  660. srsym: tsym;
  661. afterconstructionblock,
  662. exceptblock,
  663. newblock: tblocknode;
  664. newstatement: tstatementnode;
  665. pd: tprocdef;
  666. begin
  667. if assigned(procdef.struct) and
  668. (procdef.proctypeoption=potype_constructor) then
  669. begin
  670. withexceptblock:=
  671. withexceptblock and
  672. not(target_info.system in systems_garbage_collected_managed_types);
  673. { Don't test self and the vmt here. See generate_bodyexit_block }
  674. { why (JM) }
  675. oldlocalswitches:=current_settings.localswitches;
  676. current_settings.localswitches:=oldlocalswitches-[cs_check_object,cs_check_range];
  677. { call AfterConstruction for classes }
  678. if is_class(procdef.struct) then
  679. begin
  680. srsym:=search_struct_member(procdef.struct,'AFTERCONSTRUCTION');
  681. if assigned(srsym) and
  682. (srsym.typ=procsym) then
  683. begin
  684. current_filepos:=exitpos;
  685. afterconstructionblock:=internalstatements(newstatement);
  686. { first execute all constructor code. If no exception
  687. occurred then we will execute afterconstruction,
  688. otherwise we won't (the exception will jump over us) }
  689. addstatement(newstatement,tocode);
  690. { if implicit finally node wasn't created, then exit label and
  691. finalization code must be handled here and placed before
  692. afterconstruction }
  693. if not ((pi_needs_implicit_finally in flags) and
  694. (cs_implicit_exceptions in current_settings.moduleswitches)) then
  695. begin
  696. include(tocode.flags,nf_block_with_exit);
  697. addstatement(newstatement,final_asmnode);
  698. final_used:=true;
  699. end;
  700. { Self can be nil when fail is called }
  701. { if self<>nil and vmt<>nil then afterconstruction }
  702. addstatement(newstatement,cifnode.create(
  703. caddnode.create(andn,
  704. caddnode.create(unequaln,
  705. load_self_node,
  706. cnilnode.create),
  707. caddnode.create(unequaln,
  708. load_vmt_pointer_node,
  709. cnilnode.create)),
  710. ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
  711. nil));
  712. tocode:=afterconstructionblock;
  713. end
  714. else
  715. internalerror(200305106);
  716. end;
  717. if withexceptblock and (procdef.struct.typ=objectdef) then
  718. begin
  719. { Generate the implicit "fail" code for a constructor (destroy
  720. in case an exception happened) }
  721. pd:=tobjectdef(procdef.struct).find_destructor;
  722. { this will always be the case for classes, since tobject has
  723. a destructor }
  724. if assigned(pd) then
  725. begin
  726. current_filepos:=exitpos;
  727. exceptblock:=internalstatements(newstatement);
  728. { first free the instance if non-nil }
  729. { if vmt<>0 then call destructor }
  730. addstatement(newstatement,cifnode.create(
  731. caddnode.create(unequaln,
  732. load_vmt_pointer_node,
  733. cnilnode.create),
  734. { cnf_create_failed -> don't call BeforeDestruction }
  735. ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node,[cnf_create_failed]),
  736. nil));
  737. { then re-raise the exception }
  738. addstatement(newstatement,craisenode.create(nil,nil,nil));
  739. current_filepos:=entrypos;
  740. newblock:=internalstatements(newstatement);
  741. { try
  742. tocode
  743. except
  744. exceptblock
  745. end
  746. }
  747. addstatement(newstatement,ctryexceptnode.create(
  748. tocode,
  749. nil,
  750. exceptblock));
  751. tocode:=newblock;
  752. end;
  753. end;
  754. current_settings.localswitches:=oldlocalswitches;
  755. end;
  756. end;
  757. procedure tcgprocinfo.add_entry_exit_code;
  758. var
  759. finalcode,
  760. bodyentrycode,
  761. bodyexitcode,
  762. exceptcode,
  763. wrappedbody,
  764. newblock : tnode;
  765. codestatement,
  766. newstatement : tstatementnode;
  767. oldfilepos : tfileposinfo;
  768. is_constructor: boolean;
  769. begin
  770. is_constructor:=assigned(procdef.struct) and
  771. (procdef.proctypeoption=potype_constructor);
  772. oldfilepos:=current_filepos;
  773. { Generate code/locations used at start of proc }
  774. current_filepos:=entrypos;
  775. entry_asmnode:=casmnode.create_get_position;
  776. loadpara_asmnode:=casmnode.create_get_position;
  777. stackcheck_asmnode:=casmnode.create_get_position;
  778. init_asmnode:=casmnode.create_get_position;
  779. bodyentrycode:=generate_bodyentry_block;
  780. { Generate code/locations used at end of proc }
  781. current_filepos:=exitpos;
  782. exitlabel_asmnode:=casmnode.create_get_position;
  783. final_asmnode:=casmnode.create_get_position;
  784. final_used:=false;
  785. bodyexitcode:=generate_bodyexit_block;
  786. { Generate procedure by combining init+body+final,
  787. depending on the implicit finally we need to add
  788. an try...finally...end wrapper }
  789. newblock:=internalstatements(newstatement);
  790. { initialization is common for all cases }
  791. addstatement(newstatement,loadpara_asmnode);
  792. addstatement(newstatement,stackcheck_asmnode);
  793. addstatement(newstatement,entry_asmnode);
  794. addstatement(newstatement,init_asmnode);
  795. addstatement(newstatement,bodyentrycode);
  796. if (cs_implicit_exceptions in current_settings.moduleswitches) and
  797. (pi_needs_implicit_finally in flags) and
  798. { but it's useless in init/final code of units }
  799. not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) and
  800. not(po_assembler in procdef.procoptions) and
  801. not(target_info.system in systems_garbage_collected_managed_types) then
  802. begin
  803. { Generate special exception block only needed when
  804. implicit finaly is used }
  805. current_filepos:=exitpos;
  806. exceptcode:=generate_except_block;
  807. { Generate code that will be in the try...finally }
  808. finalcode:=internalstatements(codestatement);
  809. addstatement(codestatement,final_asmnode);
  810. final_used:=true;
  811. current_filepos:=entrypos;
  812. wrappedbody:=ctryfinallynode.create_implicit(
  813. code,
  814. finalcode,
  815. exceptcode);
  816. { afterconstruction must be called after final_asmnode, because it
  817. has to execute after the temps have been finalised in case of a
  818. refcounted class (afterconstruction decreases the refcount
  819. without freeing the instance if the count becomes nil, while
  820. the finalising of the temps can free the instance) }
  821. maybe_add_constructor_wrapper(wrappedbody,true);
  822. addstatement(newstatement,wrappedbody);
  823. addstatement(newstatement,exitlabel_asmnode);
  824. addstatement(newstatement,bodyexitcode);
  825. { set flag the implicit finally has been generated }
  826. include(flags,pi_has_implicit_finally);
  827. end
  828. else
  829. begin
  830. { constructors need destroy-on-exception code even if they don't
  831. have managed variables/temps }
  832. maybe_add_constructor_wrapper(code,
  833. cs_implicit_exceptions in current_settings.moduleswitches);
  834. addstatement(newstatement,code);
  835. if assigned(nestedexitlabel) then
  836. addstatement(newstatement,clabelnode.create(cnothingnode.create,nestedexitlabel));
  837. addstatement(newstatement,exitlabel_asmnode);
  838. addstatement(newstatement,bodyexitcode);
  839. if not is_constructor then
  840. begin
  841. addstatement(newstatement,final_asmnode);
  842. final_used:=true;
  843. end;
  844. end;
  845. do_firstpass(newblock);
  846. code:=newblock;
  847. current_filepos:=oldfilepos;
  848. end;
  849. procedure clearrefs(p:TObject;arg:pointer);
  850. begin
  851. if (tsym(p).typ in [localvarsym,paravarsym,staticvarsym]) then
  852. if tabstractvarsym(p).refs>1 then
  853. tabstractvarsym(p).refs:=1;
  854. end;
  855. procedure translate_registers(p:TObject;list:pointer);
  856. begin
  857. if (tsym(p).typ in [localvarsym,paravarsym,staticvarsym]) and
  858. (tabstractnormalvarsym(p).localloc.loc in [LOC_REGISTER,LOC_CREGISTER,LOC_MMREGISTER,
  859. LOC_CMMREGISTER,LOC_FPUREGISTER,LOC_CFPUREGISTER]) then
  860. begin
  861. if not(cs_no_regalloc in current_settings.globalswitches) then
  862. begin
  863. cg.translate_register(tabstractnormalvarsym(p).localloc.register);
  864. if (tabstractnormalvarsym(p).localloc.registerhi<>NR_NO) then
  865. cg.translate_register(tabstractnormalvarsym(p).localloc.registerhi);
  866. end;
  867. if cs_asm_source in current_settings.globalswitches then
  868. begin
  869. if tabstractnormalvarsym(p).localloc.registerhi<>NR_NO then
  870. begin
  871. TAsmList(list).concat(Tai_comment.Create(strpnew('Var '+tabstractnormalvarsym(p).realname+' located in register '+
  872. std_regname(tabstractnormalvarsym(p).localloc.registerhi)+':'+std_regname(tabstractnormalvarsym(p).localloc.register))));
  873. end
  874. else
  875. TAsmList(list).concat(Tai_comment.Create(strpnew('Var '+tabstractnormalvarsym(p).realname+' located in register '+
  876. std_regname(tabstractnormalvarsym(p).localloc.register))));
  877. end;
  878. end;
  879. end;
  880. const
  881. exception_flags: array[boolean] of tprocinfoflags = (
  882. [],
  883. [pi_uses_exceptions,pi_needs_implicit_finally,pi_has_implicit_finally]
  884. );
  885. procedure tcgprocinfo.setup_tempgen;
  886. begin
  887. tg:=tgobjclass.create;
  888. {$if defined(i386) or defined(x86_64) or defined(arm)}
  889. {$if defined(arm)}
  890. { frame and stack pointer must be always the same on arm thumb so it makes no
  891. sense to fiddle with a frame pointer }
  892. if GenerateThumbCode then
  893. begin
  894. framepointer:=NR_STACK_POINTER_REG;
  895. tg.direction:=1;
  896. end
  897. else
  898. {$endif defined(arm)}
  899. begin
  900. { try to strip the stack frame }
  901. { set the framepointer to esp if:
  902. - no assembler directive, those are handled in assembler_block
  903. in pstatment.pas (for cases not caught by the Delphi
  904. exception below)
  905. - no exceptions are used
  906. - no pushes are used/esp modifications, could be:
  907. * outgoing parameters on the stack on non-fixed stack target
  908. * incoming parameters on the stack
  909. * open arrays
  910. - no inline assembler
  911. or
  912. - Delphi mode
  913. - assembler directive
  914. - no pushes are used/esp modifications, could be:
  915. * outgoing parameters on the stack
  916. * incoming parameters on the stack
  917. * open arrays
  918. - no local variables
  919. - stack frame cannot be optimized if using Win64 SEH
  920. (at least with the current state of our codegenerator).
  921. }
  922. if ((po_assembler in procdef.procoptions) and
  923. (m_delphi in current_settings.modeswitches) and
  924. { localst at main_program_level is a staticsymtable }
  925. (procdef.localst.symtablelevel<>main_program_level) and
  926. (tabstractlocalsymtable(procdef.localst).count_locals = 0)) or
  927. ((cs_opt_stackframe in current_settings.optimizerswitches) and
  928. not(cs_generate_stackframes in current_settings.localswitches) and
  929. not(cs_profile in current_settings.moduleswitches) and
  930. not(po_assembler in procdef.procoptions) and
  931. not ((pi_has_stackparameter in flags)
  932. {$ifndef arm} { Outgoing parameter(s) on stack do not need stackframe on x86 targets
  933. with fixed stack. On ARM it fails, see bug #25050 }
  934. and (not paramanager.use_fixed_stack)
  935. {$endif arm}
  936. ) and
  937. ((flags*([pi_has_assembler_block,pi_is_assembler,
  938. pi_needs_stackframe]+
  939. exception_flags[(target_info.cpu=cpu_i386)
  940. {$ifndef DISABLE_WIN64_SEH}
  941. or (target_info.system=system_x86_64_win64)
  942. {$endif DISABLE_WIN64_SEH}
  943. ]))=[])
  944. )
  945. then
  946. begin
  947. { we need the parameter info here to determine if the procedure gets
  948. parameters on the stack
  949. calling generate_parameter_info doesn't hurt but it costs time
  950. (necessary to init para_stack_size)
  951. }
  952. generate_parameter_info;
  953. if not(procdef.stack_tainting_parameter(calleeside)) and
  954. not(has_assembler_child) and (para_stack_size=0) then
  955. begin
  956. { Only need to set the framepointer }
  957. framepointer:=NR_STACK_POINTER_REG;
  958. tg.direction:=1;
  959. end;
  960. end;
  961. end;
  962. {$endif defined(x86) or defined(arm)}
  963. { set the start offset to the start of the temp area in the stack }
  964. set_first_temp_offset;
  965. end;
  966. function tcgprocinfo.has_assembler_child : boolean;
  967. var
  968. hp : tprocinfo;
  969. begin
  970. result:=false;
  971. hp:=get_first_nestedproc;
  972. while assigned(hp) do
  973. begin
  974. if (hp.flags*[pi_has_assembler_block,pi_is_assembler])<>[] then
  975. begin
  976. result:=true;
  977. exit;
  978. end;
  979. hp:=tprocinfo(hp.next);
  980. end;
  981. end;
  982. procedure tcgprocinfo.generate_code_tree;
  983. var
  984. hpi : tcgprocinfo;
  985. begin
  986. { generate code for this procedure }
  987. generate_code;
  988. { process nested procedures }
  989. hpi:=tcgprocinfo(get_first_nestedproc);
  990. while assigned(hpi) do
  991. begin
  992. hpi.generate_code_tree;
  993. hpi:=tcgprocinfo(hpi.next);
  994. end;
  995. resetprocdef;
  996. end;
  997. { For SEH, the code from 'finally' blocks must be put into a separate procedures,
  998. which can be called by OS during stack unwind. This resembles nested procedures,
  999. but finalizer procedures do not have their own local variables and work directly
  1000. with the stack frame of parent. In particular, the tempgen must be shared, so
  1001. 1) finalizer procedure is able to finalize temps of the parent,
  1002. 2) if the finalizer procedure is complex enough to need its own temps, they are
  1003. allocated in stack frame of parent, so second-level finalizer procedures are
  1004. not needed.
  1005. Due to requirement of shared tempgen we cannot process finalizer as a regular nested
  1006. procedure (after the parent) and have to do it inline.
  1007. This is called by platform-specific tryfinallynodes during pass2.
  1008. Here we put away the codegen (which carries the register allocator state), process
  1009. the 'nested' procedure, then restore previous cg and continue processing the parent
  1010. procedure. generate_code() will create another cg, but not another tempgen because
  1011. setup_tempgen() is not called for potype_exceptfilter procedures. }
  1012. procedure tcgprocinfo.generate_exceptfilter(nestedpi: tcgprocinfo);
  1013. var
  1014. saved_cg: tcg;
  1015. saved_hlcg: thlcgobj;
  1016. {$ifdef cpu64bitalu}
  1017. saved_cg128 : tcg128;
  1018. {$else cpu64bitalu}
  1019. saved_cg64 : tcg64;
  1020. {$endif cpu64bitalu}
  1021. begin
  1022. if nestedpi.procdef.proctypeoption<>potype_exceptfilter then
  1023. InternalError(201201141);
  1024. { flush code generated this far }
  1025. aktproccode.concatlist(current_asmdata.CurrAsmList);
  1026. { save the codegen }
  1027. saved_cg:=cg;
  1028. saved_hlcg:=hlcg;
  1029. cg:=nil;
  1030. hlcg:=nil;
  1031. {$ifdef cpu64bitalu}
  1032. saved_cg128:=cg128;
  1033. cg128:=nil;
  1034. {$else cpu64bitalu}
  1035. saved_cg64:=cg64;
  1036. cg64:=nil;
  1037. {$endif cpu64bitalu}
  1038. nestedpi.generate_code;
  1039. { prevents generating code the second time when processing nested procedures }
  1040. nestedpi.resetprocdef;
  1041. cg:=saved_cg;
  1042. hlcg:=saved_hlcg;
  1043. {$ifdef cpu64bitalu}
  1044. cg128:=saved_cg128;
  1045. {$else cpu64bitalu}
  1046. cg64:=saved_cg64;
  1047. {$endif cpu64bitalu}
  1048. add_reg_instruction_hook:[email protected]_reg_instruction;
  1049. end;
  1050. procedure TCGProcinfo.CreateInlineInfo;
  1051. begin
  1052. new(procdef.inlininginfo);
  1053. include(procdef.procoptions,po_has_inlininginfo);
  1054. procdef.inlininginfo^.code:=code.getcopy;
  1055. procdef.inlininginfo^.flags:=flags;
  1056. { The blocknode needs to set an exit label }
  1057. if procdef.inlininginfo^.code.nodetype=blockn then
  1058. include(procdef.inlininginfo^.code.flags,nf_block_with_exit);
  1059. end;
  1060. function searchusercode(var n: tnode; arg: pointer): foreachnoderesult;
  1061. begin
  1062. if nf_usercode_entry in n.flags then
  1063. begin
  1064. pnode(arg)^:=n;
  1065. result:=fen_norecurse_true
  1066. end
  1067. else
  1068. result:=fen_false;
  1069. end;
  1070. function TCGProcinfo.GetUserCode : tnode;
  1071. var
  1072. n : tnode;
  1073. begin
  1074. n:=nil;
  1075. foreachnodestatic(code,@searchusercode,@n);
  1076. if not(assigned(n)) then
  1077. internalerror(2013111001);
  1078. result:=n;
  1079. end;
  1080. procedure tcgprocinfo.generate_code;
  1081. var
  1082. old_current_procinfo : tprocinfo;
  1083. oldmaxfpuregisters : longint;
  1084. oldfilepos : tfileposinfo;
  1085. old_current_structdef : tabstractrecorddef;
  1086. templist : TAsmList;
  1087. headertai : tai;
  1088. i : integer;
  1089. varsym : tabstractnormalvarsym;
  1090. {RedoDFA : boolean;}
  1091. begin
  1092. { the initialization procedure can be empty, then we
  1093. don't need to generate anything. When it was an empty
  1094. procedure there would be at least a blocknode }
  1095. if not assigned(code) then
  1096. exit;
  1097. { We need valid code }
  1098. if Errorcount<>0 then
  1099. exit;
  1100. { No code can be generated for generic template }
  1101. if (df_generic in procdef.defoptions) then
  1102. internalerror(200511152);
  1103. { For regular procedures the RA and Tempgen shall not be available yet,
  1104. but exception filters reuse Tempgen of parent }
  1105. if assigned(tg)<>(procdef.proctypeoption=potype_exceptfilter) then
  1106. internalerror(200309201);
  1107. old_current_procinfo:=current_procinfo;
  1108. oldfilepos:=current_filepos;
  1109. old_current_structdef:=current_structdef;
  1110. oldmaxfpuregisters:=current_settings.maxfpuregisters;
  1111. current_procinfo:=self;
  1112. current_filepos:=entrypos;
  1113. current_structdef:=procdef.struct;
  1114. { store start of user code, it must be a block node, it will be used later one to
  1115. check variable lifeness }
  1116. include(code.flags,nf_usercode_entry);
  1117. { add wrapping code if necessary (initialization of typed constants on
  1118. some platforms, initing of local variables and out parameters with
  1119. trashing values, ... }
  1120. { init/final code must be wrapped later (after code for main proc body
  1121. has been generated }
  1122. if not(current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1123. code:=cnodeutils.wrap_proc_body(procdef,code);
  1124. { automatic inlining? }
  1125. if (cs_opt_autoinline in current_settings.optimizerswitches) and
  1126. { inlining not turned off? }
  1127. (cs_do_inline in current_settings.localswitches) and
  1128. { no inlining yet? }
  1129. not(po_has_inlininginfo in procdef.procoptions) and not(has_nestedprocs) and
  1130. not(procdef.proctypeoption in [potype_proginit,potype_unitinit,potype_unitfinalize,potype_constructor,
  1131. potype_destructor,potype_class_constructor,potype_class_destructor]) and
  1132. ((procdef.procoptions*[po_exports,po_external,po_interrupt,po_virtualmethod,po_iocheck])=[]) and
  1133. (not(procdef.proccalloption in [pocall_safecall])) and
  1134. { rough approximation if we should auto inline }
  1135. (node_count(code)<=10) then
  1136. begin
  1137. { Can we inline this procedure? }
  1138. if checknodeinlining(procdef) then
  1139. begin
  1140. Message1(cg_d_autoinlining,procdef.GetTypeName);
  1141. include(procdef.procoptions,po_inline);
  1142. CreateInlineInfo;
  1143. end;
  1144. end;
  1145. templist:=TAsmList.create;
  1146. { add parast/localst to symtablestack }
  1147. add_to_symtablestack;
  1148. { clear register count }
  1149. procdef.localst.SymList.ForEachCall(@clearrefs,nil);
  1150. procdef.parast.SymList.ForEachCall(@clearrefs,nil);
  1151. { there's always a call to FPC_INITIALIZEUNITS/FPC_DO_EXIT in the main program }
  1152. if (procdef.localst.symtablelevel=main_program_level) and
  1153. (not current_module.is_unit) then
  1154. include(flags,pi_do_call);
  1155. { set implicit_finally flag when there are locals/paras to be finalized }
  1156. procdef.parast.SymList.ForEachCall(@check_finalize_paras,nil);
  1157. procdef.localst.SymList.ForEachCall(@check_finalize_locals,nil);
  1158. {$ifdef SUPPORT_SAFECALL}
  1159. { set implicit_finally flag for if procedure is safecall }
  1160. if (tf_safecall_exceptions in target_info.flags) and
  1161. (procdef.proccalloption=pocall_safecall) then
  1162. include(flags, pi_needs_implicit_finally);
  1163. {$endif}
  1164. { firstpass everything }
  1165. flowcontrol:=[];
  1166. do_firstpass(code);
  1167. {$if defined(i386) or defined(i8086)}
  1168. procdef.fpu_used:=node_resources_fpu(code);
  1169. if procdef.fpu_used>0 then
  1170. include(flags,pi_uses_fpu);
  1171. {$endif i386 or i8086}
  1172. { Print the node to tree.log }
  1173. if paraprintnodetree=1 then
  1174. printproc( 'after the firstpass');
  1175. { do this before adding the entry code else the tail recursion recognition won't work,
  1176. if this causes troubles, it must be if'ed
  1177. }
  1178. if (cs_opt_tailrecursion in current_settings.optimizerswitches) and
  1179. (pi_is_recursive in flags) then
  1180. do_opttail(code,procdef);
  1181. if cs_opt_constant_propagate in current_settings.optimizerswitches then
  1182. do_optconstpropagate(code);
  1183. if (cs_opt_nodedfa in current_settings.optimizerswitches) and
  1184. { creating dfa is not always possible }
  1185. ((flags*[pi_has_assembler_block,pi_uses_exceptions,pi_is_assembler])=[]) then
  1186. begin
  1187. dfabuilder:=TDFABuilder.Create;
  1188. dfabuilder.createdfainfo(code);
  1189. { when life info is available, we can give more sophisticated warning about unintialized
  1190. variables }
  1191. { iterate through life info of the first node }
  1192. for i:=0 to dfabuilder.nodemap.count-1 do
  1193. begin
  1194. if DFASetIn(GetUserCode.optinfo^.life,i) then
  1195. case tnode(dfabuilder.nodemap[i]).nodetype of
  1196. loadn:
  1197. begin
  1198. varsym:=tabstractnormalvarsym(tloadnode(dfabuilder.nodemap[i]).symtableentry);
  1199. { Give warning/note for living locals, result and parameters, but only about the current
  1200. symtables }
  1201. if assigned(varsym.owner) and
  1202. (((varsym.owner=procdef.localst) and
  1203. (procdef.localst.symtablelevel=varsym.owner.symtablelevel)
  1204. ) or
  1205. ((varsym.owner=procdef.parast) and
  1206. (varsym.typ=paravarsym) and
  1207. (procdef.parast.symtablelevel=varsym.owner.symtablelevel) and
  1208. { all parameters except out parameters are initialized by the caller }
  1209. (tparavarsym(varsym).varspez=vs_out)
  1210. ) or
  1211. ((vo_is_funcret in varsym.varoptions) and
  1212. (procdef.parast.symtablelevel=varsym.owner.symtablelevel)
  1213. )
  1214. ) and
  1215. not(vo_is_external in varsym.varoptions) then
  1216. begin
  1217. if (vo_is_funcret in varsym.varoptions) then
  1218. CGMessage(sym_w_function_result_uninitialized)
  1219. else
  1220. begin
  1221. if not (vo_is_typed_const in varsym.varoptions) then
  1222. if varsym.typ=paravarsym then
  1223. CGMessage1(sym_w_uninitialized_variable,varsym.realname)
  1224. else
  1225. CGMessage1(sym_w_uninitialized_local_variable,varsym.realname);
  1226. end;
  1227. end;
  1228. end;
  1229. end;
  1230. end;
  1231. include(flags,pi_dfaavailable);
  1232. end;
  1233. if (pi_dfaavailable in flags) and (cs_opt_dead_store_eliminate in current_settings.optimizerswitches) then
  1234. do_optdeadstoreelim(code);
  1235. if (cs_opt_loopstrength in current_settings.optimizerswitches)
  1236. { our induction variable strength reduction doesn't like
  1237. for loops with more than one entry }
  1238. and not(pi_has_label in flags) then
  1239. begin
  1240. {RedoDFA:=}OptimizeInductionVariables(code);
  1241. end;
  1242. if cs_opt_nodecse in current_settings.optimizerswitches then
  1243. do_optcse(code);
  1244. if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
  1245. (procdef.proctypeoption in [potype_operator,potype_procedure,potype_function]) and
  1246. (code.nodetype=blockn) and (tblocknode(code).statements=nil) then
  1247. procdef.isempty:=true;
  1248. { add implicit entry and exit code }
  1249. add_entry_exit_code;
  1250. { only do secondpass if there are no errors }
  1251. if (ErrorCount=0) then
  1252. begin
  1253. create_hlcodegen;
  1254. if (procdef.proctypeoption<>potype_exceptfilter) then
  1255. setup_tempgen;
  1256. { Create register allocator, must come after framepointer is known }
  1257. hlcg.init_register_allocators;
  1258. generate_parameter_info;
  1259. { allocate got register if needed }
  1260. allocate_got_register(aktproccode);
  1261. { Allocate space in temp/registers for parast and localst }
  1262. current_filepos:=entrypos;
  1263. gen_alloc_symtable(aktproccode,procdef,procdef.parast);
  1264. gen_alloc_symtable(aktproccode,procdef,procdef.localst);
  1265. { Store temp offset for information about 'real' temps }
  1266. tempstart:=tg.lasttemp;
  1267. { Generate code to load register parameters in temps and insert local
  1268. copies for values parameters. This must be done before the code for the
  1269. body is generated because the localloc is updated.
  1270. Note: The generated code will be inserted after the code generation of
  1271. the body is finished, because only then the position is known }
  1272. {$ifdef oldregvars}
  1273. assign_regvars(code);
  1274. {$endif oldreg}
  1275. current_filepos:=entrypos;
  1276. hlcg.gen_load_para_value(templist);
  1277. { caller paraloc info is also necessary in the stackframe_entry
  1278. code of the ppc (and possibly other processors) }
  1279. procdef.init_paraloc_info(callerside);
  1280. { generate code for the node tree }
  1281. do_secondpass(code);
  1282. aktproccode.concatlist(current_asmdata.CurrAsmList);
  1283. { The position of the loadpara_asmnode is now known }
  1284. aktproccode.insertlistafter(loadpara_asmnode.currenttai,templist);
  1285. { first generate entry and initialize code with the correct
  1286. position and switches }
  1287. current_filepos:=entrypos;
  1288. current_settings.localswitches:=entryswitches;
  1289. cg.set_regalloc_live_range_direction(rad_backwards);
  1290. hlcg.gen_entry_code(templist);
  1291. aktproccode.insertlistafter(entry_asmnode.currenttai,templist);
  1292. hlcg.gen_initialize_code(templist);
  1293. aktproccode.insertlistafter(init_asmnode.currenttai,templist);
  1294. { now generate finalize and exit code with the correct position
  1295. and switches }
  1296. current_filepos:=exitpos;
  1297. current_settings.localswitches:=exitswitches;
  1298. cg.set_regalloc_live_range_direction(rad_forward);
  1299. if assigned(finalize_procinfo) then
  1300. generate_exceptfilter(tcgprocinfo(finalize_procinfo))
  1301. else
  1302. begin
  1303. hlcg.gen_finalize_code(templist);
  1304. { the finalcode must be concated if there was no position available,
  1305. using insertlistafter will result in an insert at the start
  1306. when currentai=nil }
  1307. if assigned(final_asmnode) and assigned(final_asmnode.currenttai) then
  1308. aktproccode.insertlistafter(final_asmnode.currenttai,templist)
  1309. else
  1310. aktproccode.concatlist(templist);
  1311. end;
  1312. { insert exit label at the correct position }
  1313. hlcg.a_label(templist,CurrExitLabel);
  1314. if assigned(exitlabel_asmnode.currenttai) then
  1315. aktproccode.insertlistafter(exitlabel_asmnode.currenttai,templist)
  1316. else
  1317. aktproccode.concatlist(templist);
  1318. { exit code }
  1319. hlcg.gen_exit_code(templist);
  1320. aktproccode.concatlist(templist);
  1321. {$ifdef OLDREGVARS}
  1322. { note: this must be done only after as much code as possible has }
  1323. { been generated. The result is that when you ungetregister() a }
  1324. { regvar, it will actually free the regvar (and alse free the }
  1325. { the regvars at the same time). Doing this too early will }
  1326. { confuse the register allocator, as the regvars will still be }
  1327. { used. It should be done before loading the result regs (so }
  1328. { they don't conflict with the regvars) and before }
  1329. { gen_entry_code (that one has to be able to allocate the }
  1330. { regvars again) (JM) }
  1331. free_regvars(aktproccode);
  1332. {$endif OLDREGVARS}
  1333. { generate symbol and save end of header position }
  1334. current_filepos:=entrypos;
  1335. hlcg.gen_proc_symbol(templist);
  1336. headertai:=tai(templist.last);
  1337. { insert symbol }
  1338. aktproccode.insertlist(templist);
  1339. { Free space in temp/registers for parast and localst, must be
  1340. done after gen_entry_code }
  1341. current_filepos:=exitpos;
  1342. { make sure the got/pic register doesn't get freed in the }
  1343. { middle of a loop }
  1344. if (cs_create_pic in current_settings.moduleswitches) and
  1345. (pi_needs_got in flags) and
  1346. (got<>NR_NO) then
  1347. cg.a_reg_sync(aktproccode,got);
  1348. gen_free_symtable(aktproccode,procdef.localst);
  1349. gen_free_symtable(aktproccode,procdef.parast);
  1350. { add code that will load the return value, this is not done
  1351. for assembler routines when they didn't reference the result
  1352. variable }
  1353. hlcg.gen_load_return_value(templist);
  1354. aktproccode.concatlist(templist);
  1355. { Already reserve all registers for stack checking code and
  1356. generate the call to the helper function }
  1357. if not(tf_no_generic_stackcheck in target_info.flags) and
  1358. (cs_check_stack in entryswitches) and
  1359. not(po_assembler in procdef.procoptions) and
  1360. (procdef.proctypeoption<>potype_proginit) then
  1361. begin
  1362. current_filepos:=entrypos;
  1363. gen_stack_check_call(templist);
  1364. aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
  1365. end;
  1366. { this code (got loading) comes before everything which has }
  1367. { already been generated, so reset the info about already }
  1368. { backwards extended registers (so their live range can be }
  1369. { extended backwards even further if needed) }
  1370. { This code must be }
  1371. { a) generated after do_secondpass has been called }
  1372. { (because pi_needs_got may be set there) }
  1373. { b) generated before register allocation, because the }
  1374. { got/pic register can be a virtual one }
  1375. { c) inserted before the entry code, because the entry }
  1376. { code may need global symbols such as init rtti }
  1377. { d) inserted after the stackframe allocation, because }
  1378. { this register may have to be spilled }
  1379. cg.set_regalloc_live_range_direction(rad_backwards_reinit);
  1380. current_filepos:=entrypos;
  1381. { load got if necessary }
  1382. cg.g_maybe_got_init(templist);
  1383. aktproccode.insertlistafter(headertai,templist);
  1384. { re-enable if more code at the end is ever generated here
  1385. cg.set_regalloc_live_range_direction(rad_forward);
  1386. }
  1387. {$ifndef NoOpt}
  1388. {$ifndef i386}
  1389. if (cs_opt_scheduler in current_settings.optimizerswitches) and
  1390. { do not optimize pure assembler procedures }
  1391. not(pi_is_assembler in flags) then
  1392. preregallocschedule(aktproccode);
  1393. {$endif i386}
  1394. {$endif NoOpt}
  1395. { The procedure body is finished, we can now
  1396. allocate the registers }
  1397. cg.do_register_allocation(aktproccode,headertai);
  1398. { translate imag. register to their real counter parts
  1399. this is necessary for debuginfo and verbose assembler output
  1400. when SSA will be implented, this will be more complicated because we've to
  1401. maintain location lists }
  1402. procdef.parast.SymList.ForEachCall(@translate_registers,templist);
  1403. procdef.localst.SymList.ForEachCall(@translate_registers,templist);
  1404. if (cs_create_pic in current_settings.moduleswitches) and
  1405. (pi_needs_got in flags) and
  1406. not(cs_no_regalloc in current_settings.globalswitches) and
  1407. (got<>NR_NO) then
  1408. cg.translate_register(got);
  1409. { Add save and restore of used registers }
  1410. current_filepos:=entrypos;
  1411. gen_save_used_regs(templist);
  1412. { Remember the last instruction of register saving block
  1413. (may be =nil for e.g. assembler procedures) }
  1414. endprologue_ai:=templist.last;
  1415. aktproccode.insertlistafter(headertai,templist);
  1416. current_filepos:=exitpos;
  1417. gen_restore_used_regs(aktproccode);
  1418. { We know the size of the stack, now we can generate the
  1419. parameter that is passed to the stack checking code }
  1420. if not(tf_no_generic_stackcheck in target_info.flags) and
  1421. (cs_check_stack in entryswitches) and
  1422. not(po_assembler in procdef.procoptions) and
  1423. (procdef.proctypeoption<>potype_proginit) then
  1424. begin
  1425. current_filepos:=entrypos;
  1426. gen_stack_check_size_para(templist);
  1427. aktproccode.insertlistafter(stackcheck_asmnode.currenttai,templist)
  1428. end;
  1429. { Add entry code (stack allocation) after header }
  1430. current_filepos:=entrypos;
  1431. gen_proc_entry_code(templist);
  1432. aktproccode.insertlistafter(headertai,templist);
  1433. {$ifdef SUPPORT_SAFECALL}
  1434. { Set return value of safecall procedure if implicit try/finally blocks are disabled }
  1435. if not (cs_implicit_exceptions in current_settings.moduleswitches) and
  1436. (tf_safecall_exceptions in target_info.flags) and
  1437. (procdef.proccalloption=pocall_safecall) then
  1438. cg.a_load_const_reg(aktproccode,OS_ADDR,0,NR_FUNCTION_RETURN_REG);
  1439. {$endif}
  1440. { Add exit code at the end }
  1441. current_filepos:=exitpos;
  1442. gen_proc_exit_code(templist);
  1443. aktproccode.concatlist(templist);
  1444. { check if the implicit finally has been generated. The flag
  1445. should already be set in pass1 }
  1446. if (cs_implicit_exceptions in current_settings.moduleswitches) and
  1447. not(procdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) and
  1448. (pi_needs_implicit_finally in flags) and
  1449. not(po_assembler in procdef.procoptions) and
  1450. not(pi_has_implicit_finally in flags) and
  1451. not(target_info.system in systems_garbage_collected_managed_types) then
  1452. internalerror(200405231);
  1453. {$ifndef NoOpt}
  1454. if not(cs_no_regalloc in current_settings.globalswitches) then
  1455. begin
  1456. if (cs_opt_level1 in current_settings.optimizerswitches) and
  1457. { do not optimize pure assembler procedures }
  1458. not(pi_is_assembler in flags) then
  1459. optimize(aktproccode);
  1460. {$ifndef i386}
  1461. { schedule after assembler optimization, it could have brought up
  1462. new schedule possibilities }
  1463. if (cs_opt_scheduler in current_settings.optimizerswitches) and
  1464. { do not optimize pure assembler procedures }
  1465. not(pi_is_assembler in flags) then
  1466. preregallocschedule(aktproccode);
  1467. {$endif i386}
  1468. end;
  1469. {$endif NoOpt}
  1470. {$ifdef ARM}
  1471. { because of the limited constant size of the arm, all data access is done pc relative }
  1472. finalizearmcode(aktproccode,aktlocaldata);
  1473. {$endif ARM}
  1474. {$ifdef AVR}
  1475. { because of the limited branch distance of cond. branches, they must be replaced
  1476. sometimes by normal jmps and an inverse branch }
  1477. finalizeavrcode(aktproccode);
  1478. {$endif AVR}
  1479. { Add end symbol and debug info }
  1480. { this must be done after the pcrelativedata is appended else the distance calculation of
  1481. insertpcrelativedata will be wrong, further the pc indirect data is part of the procedure
  1482. so it should be inserted before the end symbol (FK)
  1483. }
  1484. current_filepos:=exitpos;
  1485. hlcg.gen_proc_symbol_end(templist);
  1486. aktproccode.concatlist(templist);
  1487. {$ifdef fpc_compiler_has_fixup_jmps}
  1488. fixup_jmps(aktproccode);
  1489. {$endif}
  1490. { insert line debuginfo }
  1491. if (cs_debuginfo in current_settings.moduleswitches) or
  1492. (cs_use_lineinfo in current_settings.globalswitches) then
  1493. current_debuginfo.insertlineinfo(aktproccode);
  1494. hlcg.record_generated_code_for_procdef(current_procinfo.procdef,aktproccode,aktlocaldata);
  1495. { only now we can remove the temps }
  1496. if (procdef.proctypeoption<>potype_exceptfilter) then
  1497. begin
  1498. tg.resettempgen;
  1499. tg.free;
  1500. tg:=nil;
  1501. end;
  1502. { stop tempgen and ra }
  1503. hlcg.done_register_allocators;
  1504. destroy_hlcodegen;
  1505. end;
  1506. dfabuilder.free;
  1507. { restore symtablestack }
  1508. remove_from_symtablestack;
  1509. { restore }
  1510. templist.free;
  1511. current_settings.maxfpuregisters:=oldmaxfpuregisters;
  1512. current_filepos:=oldfilepos;
  1513. current_structdef:=old_current_structdef;
  1514. current_procinfo:=old_current_procinfo;
  1515. end;
  1516. procedure tcgprocinfo.add_to_symtablestack;
  1517. begin
  1518. { insert symtables for the class, but only if it is no nested function }
  1519. if assigned(procdef.struct) and
  1520. not(assigned(parent) and
  1521. assigned(parent.procdef) and
  1522. assigned(parent.procdef.struct)) then
  1523. push_nested_hierarchy(procdef.struct);
  1524. { insert parasymtable in symtablestack when parsing
  1525. a function }
  1526. if procdef.parast.symtablelevel>=normal_function_level then
  1527. symtablestack.push(procdef.parast);
  1528. { insert localsymtable, except for the main procedure
  1529. (in that case the localst is the unit's static symtable,
  1530. which is already on the stack) }
  1531. if procdef.localst.symtablelevel>=normal_function_level then
  1532. symtablestack.push(procdef.localst);
  1533. end;
  1534. procedure tcgprocinfo.remove_from_symtablestack;
  1535. begin
  1536. { remove localsymtable }
  1537. if procdef.localst.symtablelevel>=normal_function_level then
  1538. symtablestack.pop(procdef.localst);
  1539. { remove parasymtable }
  1540. if procdef.parast.symtablelevel>=normal_function_level then
  1541. symtablestack.pop(procdef.parast);
  1542. { remove symtables for the class, but only if it is no nested function }
  1543. if assigned(procdef.struct) and
  1544. not(assigned(parent) and
  1545. assigned(parent.procdef) and
  1546. assigned(parent.procdef.struct)) then
  1547. pop_nested_hierarchy(procdef.struct);
  1548. end;
  1549. procedure tcgprocinfo.resetprocdef;
  1550. begin
  1551. { remove code tree, if not inline procedure }
  1552. if assigned(code) then
  1553. begin
  1554. { the inline procedure has already got a copy of the tree
  1555. stored in procdef.inlininginfo }
  1556. code.free;
  1557. code:=nil;
  1558. end;
  1559. end;
  1560. procedure tcgprocinfo.parse_body;
  1561. var
  1562. old_current_procinfo : tprocinfo;
  1563. old_block_type : tblock_type;
  1564. st : TSymtable;
  1565. old_current_structdef: tabstractrecorddef;
  1566. old_current_genericdef,
  1567. old_current_specializedef: tstoreddef;
  1568. old_parse_generic: boolean;
  1569. begin
  1570. old_current_procinfo:=current_procinfo;
  1571. old_block_type:=block_type;
  1572. old_current_structdef:=current_structdef;
  1573. old_current_genericdef:=current_genericdef;
  1574. old_current_specializedef:=current_specializedef;
  1575. old_parse_generic:=parse_generic;
  1576. current_procinfo:=self;
  1577. current_structdef:=procdef.struct;
  1578. if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then
  1579. begin
  1580. current_genericdef:=current_structdef;
  1581. parse_generic:=true;
  1582. end;
  1583. if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then
  1584. current_specializedef:=current_structdef;
  1585. { calculate the lexical level }
  1586. if procdef.parast.symtablelevel>maxnesting then
  1587. Message(parser_e_too_much_lexlevel);
  1588. block_type:=bt_body;
  1589. {$ifdef state_tracking}
  1590. { aktstate:=Tstate_storage.create;}
  1591. {$endif state_tracking}
  1592. { allocate the symbol for this procedure }
  1593. alloc_proc_symbol(procdef);
  1594. { add parast/localst to symtablestack }
  1595. add_to_symtablestack;
  1596. { save entry info }
  1597. entrypos:=current_filepos;
  1598. entryswitches:=current_settings.localswitches;
  1599. if (df_generic in procdef.defoptions) then
  1600. begin
  1601. { start token recorder for generic template }
  1602. procdef.initgeneric;
  1603. current_scanner.startrecordtokens(procdef.generictokenbuf);
  1604. end;
  1605. { parse the code ... }
  1606. code:=block(current_module.islibrary);
  1607. if (df_generic in procdef.defoptions) then
  1608. begin
  1609. { stop token recorder for generic template }
  1610. current_scanner.stoprecordtokens;
  1611. { Give an error for accesses in the static symtable that aren't visible
  1612. outside the current unit }
  1613. st:=procdef.owner;
  1614. while (st.symtabletype=ObjectSymtable) do
  1615. st:=st.defowner.owner;
  1616. if (pi_uses_static_symtable in flags) and
  1617. (st.symtabletype<>staticsymtable) then
  1618. Comment(V_Error,'Global Generic template references static symtable');
  1619. end;
  1620. { save exit info }
  1621. exitswitches:=current_settings.localswitches;
  1622. exitpos:=last_endtoken_filepos;
  1623. { the procedure is now defined }
  1624. procdef.forwarddef:=false;
  1625. if assigned(code) then
  1626. begin
  1627. { get a better entry point }
  1628. entrypos:=code.fileinfo;
  1629. { Finish type checking pass }
  1630. do_typecheckpass(code);
  1631. if assigned(procdef.parentfpinitblock) then
  1632. begin
  1633. tblocknode(code).left:=cstatementnode.create(procdef.parentfpinitblock,tblocknode(code).left);
  1634. do_typecheckpass(tblocknode(code).left);
  1635. procdef.parentfpinitblock:=nil;
  1636. end;
  1637. end;
  1638. { Check for unused labels, forwards, symbols for procedures. Static
  1639. symtable is checked in pmodules.
  1640. The check must be done after the typecheckpass }
  1641. if (Errorcount=0) and
  1642. (tstoredsymtable(procdef.localst).symtabletype<>staticsymtable) then
  1643. begin
  1644. { check if forwards are resolved }
  1645. tstoredsymtable(procdef.localst).check_forwards;
  1646. { check if all labels are used }
  1647. tstoredsymtable(procdef.localst).checklabels;
  1648. { check for unused symbols, but only if there is no asm block }
  1649. if not(pi_has_assembler_block in flags) then
  1650. begin
  1651. tstoredsymtable(procdef.localst).allsymbolsused;
  1652. tstoredsymtable(procdef.parast).allsymbolsused;
  1653. end;
  1654. end;
  1655. if (po_inline in procdef.procoptions) and
  1656. { Can we inline this procedure? }
  1657. checknodeinlining(procdef) then
  1658. CreateInlineInfo;
  1659. { Print the node to tree.log }
  1660. if paraprintnodetree=1 then
  1661. printproc( 'after parsing');
  1662. { ... remove symbol tables }
  1663. remove_from_symtablestack;
  1664. {$ifdef state_tracking}
  1665. { aktstate.destroy;}
  1666. {$endif state_tracking}
  1667. current_structdef:=old_current_structdef;
  1668. current_genericdef:=old_current_genericdef;
  1669. current_specializedef:=old_current_specializedef;
  1670. current_procinfo:=old_current_procinfo;
  1671. parse_generic:=old_parse_generic;
  1672. { Restore old state }
  1673. block_type:=old_block_type;
  1674. end;
  1675. {****************************************************************************
  1676. PROCEDURE/FUNCTION PARSING
  1677. ****************************************************************************}
  1678. procedure check_init_paras(p:TObject;arg:pointer);
  1679. begin
  1680. if tsym(p).typ<>paravarsym then
  1681. exit;
  1682. with tparavarsym(p) do
  1683. if (is_managed_type(vardef) and
  1684. (varspez in [vs_value,vs_out])) or
  1685. (is_shortstring(vardef) and
  1686. (varspez=vs_value)) then
  1687. include(current_procinfo.flags,pi_do_call);
  1688. end;
  1689. procedure read_proc_body(old_current_procinfo:tprocinfo;pd:tprocdef);
  1690. {
  1691. Parses the procedure directives, then parses the procedure body, then
  1692. generates the code for it
  1693. }
  1694. var
  1695. oldfailtokenmode : tmodeswitches;
  1696. isnestedproc : boolean;
  1697. begin
  1698. Message1(parser_d_procedure_start,pd.fullprocname(false));
  1699. { create a new procedure }
  1700. current_procinfo:=cprocinfo.create(old_current_procinfo);
  1701. current_module.procinfo:=current_procinfo;
  1702. current_procinfo.procdef:=pd;
  1703. isnestedproc:=(current_procinfo.procdef.parast.symtablelevel>normal_function_level);
  1704. { Insert mangledname }
  1705. pd.aliasnames.insert(pd.mangledname);
  1706. { Handle Export of this procedure }
  1707. if (po_exports in pd.procoptions) and
  1708. (target_info.system in [system_i386_os2,system_i386_emx]) then
  1709. begin
  1710. pd.aliasnames.insert(pd.procsym.realname);
  1711. if cs_link_deffile in current_settings.globalswitches then
  1712. deffile.AddExport(pd.mangledname);
  1713. end;
  1714. { Insert result variables in the localst }
  1715. insert_funcret_local(pd);
  1716. { check if there are para's which require initing -> set }
  1717. { pi_do_call (if not yet set) }
  1718. if not(pi_do_call in current_procinfo.flags) then
  1719. pd.parast.SymList.ForEachCall(@check_init_paras,nil);
  1720. { set _FAIL as keyword if constructor }
  1721. if (pd.proctypeoption=potype_constructor) then
  1722. begin
  1723. oldfailtokenmode:=tokeninfo^[_FAIL].keyword;
  1724. tokeninfo^[_FAIL].keyword:=alllanguagemodes;
  1725. end;
  1726. tcgprocinfo(current_procinfo).parse_body;
  1727. { We can't support inlining for procedures that have nested
  1728. procedures because the nested procedures use a fixed offset
  1729. for accessing locals in the parent procedure (PFV) }
  1730. if current_procinfo.has_nestedprocs then
  1731. begin
  1732. if (df_generic in current_procinfo.procdef.defoptions) then
  1733. Comment(V_Error,'Generic methods cannot have nested procedures')
  1734. else
  1735. if (po_inline in current_procinfo.procdef.procoptions) then
  1736. begin
  1737. Message1(parser_h_not_supported_for_inline,'nested procedures');
  1738. Message(parser_h_inlining_disabled);
  1739. exclude(current_procinfo.procdef.procoptions,po_inline);
  1740. end;
  1741. end;
  1742. { When it's a nested procedure then defer the code generation,
  1743. when back at normal function level then generate the code
  1744. for all defered nested procedures and the current procedure }
  1745. if not isnestedproc then
  1746. begin
  1747. if not(df_generic in current_procinfo.procdef.defoptions) then
  1748. tcgprocinfo(current_procinfo).generate_code_tree;
  1749. end;
  1750. { reset _FAIL as _SELF normal }
  1751. if (pd.proctypeoption=potype_constructor) then
  1752. tokeninfo^[_FAIL].keyword:=oldfailtokenmode;
  1753. { release procinfo }
  1754. if tprocinfo(current_module.procinfo)<>current_procinfo then
  1755. internalerror(200304274);
  1756. current_module.procinfo:=current_procinfo.parent;
  1757. { For specialization we didn't record the last semicolon. Moving this parsing
  1758. into the parse_body routine is not done because of having better file position
  1759. information available }
  1760. if not(df_specialization in current_procinfo.procdef.defoptions) then
  1761. consume(_SEMICOLON);
  1762. if not isnestedproc then
  1763. { current_procinfo is checked for nil later on }
  1764. freeandnil(current_procinfo);
  1765. end;
  1766. procedure read_proc(isclassmethod:boolean; usefwpd: tprocdef);
  1767. {
  1768. Parses the procedure directives, then parses the procedure body, then
  1769. generates the code for it
  1770. }
  1771. var
  1772. old_current_procinfo : tprocinfo;
  1773. old_current_structdef: tabstractrecorddef;
  1774. old_current_genericdef,
  1775. old_current_specializedef: tstoreddef;
  1776. pdflags : tpdflags;
  1777. pd,firstpd : tprocdef;
  1778. s : string;
  1779. begin
  1780. { save old state }
  1781. old_current_procinfo:=current_procinfo;
  1782. old_current_structdef:=current_structdef;
  1783. old_current_genericdef:=current_genericdef;
  1784. old_current_specializedef:=current_specializedef;
  1785. { reset current_procinfo.procdef to nil to be sure that nothing is writing
  1786. to another procdef }
  1787. current_procinfo:=nil;
  1788. current_structdef:=nil;
  1789. current_genericdef:=nil;
  1790. current_specializedef:=nil;
  1791. if not assigned(usefwpd) then
  1792. { parse procedure declaration }
  1793. pd:=parse_proc_dec(isclassmethod,old_current_structdef)
  1794. else
  1795. pd:=usefwpd;
  1796. { set the default function options }
  1797. if parse_only then
  1798. begin
  1799. pd.forwarddef:=true;
  1800. { set also the interface flag, for better error message when the
  1801. implementation doesn't much this header }
  1802. pd.interfacedef:=true;
  1803. include(pd.procoptions,po_global);
  1804. pdflags:=[pd_interface];
  1805. end
  1806. else
  1807. begin
  1808. pdflags:=[pd_body];
  1809. if (not current_module.in_interface) then
  1810. include(pdflags,pd_implemen);
  1811. if (not current_module.is_unit) or
  1812. create_smartlink then
  1813. include(pd.procoptions,po_global);
  1814. pd.forwarddef:=false;
  1815. end;
  1816. if not assigned(usefwpd) then
  1817. begin
  1818. { parse the directives that may follow }
  1819. parse_proc_directives(pd,pdflags);
  1820. { hint directives, these can be separated by semicolons here,
  1821. that needs to be handled here with a loop (PFV) }
  1822. while try_consume_hintdirective(pd.symoptions,pd.deprecatedmsg) do
  1823. Consume(_SEMICOLON);
  1824. { Set calling convention }
  1825. handle_calling_convention(pd);
  1826. end;
  1827. { search for forward declarations }
  1828. if not proc_add_definition(pd) then
  1829. begin
  1830. { A method must be forward defined (in the object declaration) }
  1831. if assigned(pd.struct) and
  1832. (not assigned(old_current_structdef)) then
  1833. begin
  1834. MessagePos1(pd.fileinfo,parser_e_header_dont_match_any_member,pd.fullprocname(false));
  1835. tprocsym(pd.procsym).write_parameter_lists(pd);
  1836. end
  1837. else
  1838. begin
  1839. { Give a better error if there is a forward def in the interface and only
  1840. a single implementation }
  1841. firstpd:=tprocdef(tprocsym(pd.procsym).ProcdefList[0]);
  1842. if (not pd.forwarddef) and
  1843. (not pd.interfacedef) and
  1844. (tprocsym(pd.procsym).ProcdefList.Count>1) and
  1845. firstpd.forwarddef and
  1846. firstpd.interfacedef and
  1847. not(tprocsym(pd.procsym).ProcdefList.Count>2) and
  1848. { don't give an error if it may be an overload }
  1849. not(m_fpc in current_settings.modeswitches) and
  1850. (not(po_overload in pd.procoptions) or
  1851. not(po_overload in firstpd.procoptions)) then
  1852. begin
  1853. MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
  1854. tprocsym(pd.procsym).write_parameter_lists(pd);
  1855. end;
  1856. end;
  1857. end;
  1858. { Set mangled name }
  1859. proc_set_mangledname(pd);
  1860. { compile procedure when a body is needed }
  1861. if (pd_body in pdflags) then
  1862. begin
  1863. read_proc_body(old_current_procinfo,pd);
  1864. end
  1865. else
  1866. begin
  1867. { Handle imports }
  1868. if (po_external in pd.procoptions) then
  1869. begin
  1870. { External declared in implementation, and there was already a
  1871. forward (or interface) declaration then we need to generate
  1872. a stub that calls the external routine }
  1873. if (not pd.forwarddef) and
  1874. (pd.hasforward)
  1875. { it is unclear to me what's the use of the following condition,
  1876. so commented out, see also issue #18371 (FK)
  1877. and
  1878. not(
  1879. assigned(pd.import_dll) and
  1880. (target_info.system in [system_i386_wdosx,
  1881. system_arm_wince,system_i386_wince])
  1882. ) } then
  1883. begin
  1884. s:=proc_get_importname(pd);
  1885. if s<>'' then
  1886. gen_external_stub(current_asmdata.asmlists[al_procedures],pd,s);
  1887. end;
  1888. { Import DLL specified? }
  1889. if assigned(pd.import_dll) then
  1890. begin
  1891. if assigned (pd.import_name) then
  1892. current_module.AddExternalImport(pd.import_dll^,
  1893. pd.import_name^,proc_get_importname(pd),
  1894. pd.import_nr,false,false)
  1895. else
  1896. current_module.AddExternalImport(pd.import_dll^,
  1897. proc_get_importname(pd),proc_get_importname(pd),
  1898. pd.import_nr,false,true);
  1899. end
  1900. else
  1901. begin
  1902. { add import name to external list for DLL scanning }
  1903. if tf_has_dllscanner in target_info.flags then
  1904. current_module.dllscannerinputlist.Add(proc_get_importname(pd),pd);
  1905. end;
  1906. end;
  1907. end;
  1908. { make sure that references to forward-declared functions are not }
  1909. { treated as references to external symbols, needed for darwin. }
  1910. { make sure we don't change the binding of real external symbols }
  1911. if not(po_external in pd.procoptions) then
  1912. begin
  1913. if (po_global in pd.procoptions) or
  1914. (cs_profile in current_settings.moduleswitches) then
  1915. current_asmdata.DefineAsmSymbol(pd.mangledname,AB_GLOBAL,AT_FUNCTION)
  1916. else
  1917. current_asmdata.DefineAsmSymbol(pd.mangledname,AB_LOCAL,AT_FUNCTION);
  1918. end;
  1919. current_structdef:=old_current_structdef;
  1920. current_genericdef:=old_current_genericdef;
  1921. current_specializedef:=old_current_specializedef;
  1922. current_procinfo:=old_current_procinfo;
  1923. end;
  1924. {****************************************************************************
  1925. DECLARATION PARSING
  1926. ****************************************************************************}
  1927. { search in symtablestack for not complete classes }
  1928. procedure check_forward_class(p:TObject;arg:pointer);
  1929. begin
  1930. if (tsym(p).typ=typesym) and
  1931. (ttypesym(p).typedef.typ=objectdef) and
  1932. (oo_is_forward in tobjectdef(ttypesym(p).typedef).objectoptions) then
  1933. MessagePos1(tsym(p).fileinfo,sym_e_forward_type_not_resolved,tsym(p).realname);
  1934. end;
  1935. procedure read_declarations(islibrary : boolean);
  1936. var
  1937. is_classdef:boolean;
  1938. begin
  1939. is_classdef:=false;
  1940. repeat
  1941. if not assigned(current_procinfo) then
  1942. internalerror(200304251);
  1943. case token of
  1944. _LABEL:
  1945. label_dec;
  1946. _CONST:
  1947. const_dec;
  1948. _TYPE:
  1949. type_dec;
  1950. _VAR:
  1951. var_dec;
  1952. _THREADVAR:
  1953. threadvar_dec;
  1954. _CLASS:
  1955. begin
  1956. is_classdef:=false;
  1957. if try_to_consume(_CLASS) then
  1958. begin
  1959. { class modifier is only allowed for procedures, functions, }
  1960. { constructors, destructors }
  1961. if not(token in [_FUNCTION,_PROCEDURE,_CONSTRUCTOR,_DESTRUCTOR,_OPERATOR]) and
  1962. not((token=_ID) and (idtoken=_OPERATOR)) then
  1963. Message(parser_e_procedure_or_function_expected);
  1964. if is_interface(current_structdef) then
  1965. Message(parser_e_no_static_method_in_interfaces)
  1966. else
  1967. { class methods are also allowed for Objective-C protocols }
  1968. is_classdef:=true;
  1969. end;
  1970. end;
  1971. _CONSTRUCTOR,
  1972. _DESTRUCTOR,
  1973. _FUNCTION,
  1974. _PROCEDURE,
  1975. _OPERATOR:
  1976. begin
  1977. read_proc(is_classdef,nil);
  1978. is_classdef:=false;
  1979. end;
  1980. _EXPORTS:
  1981. begin
  1982. if (current_procinfo.procdef.localst.symtablelevel>main_program_level) then
  1983. begin
  1984. Message(parser_e_syntax_error);
  1985. consume_all_until(_SEMICOLON);
  1986. end
  1987. else if islibrary or
  1988. (target_info.system in systems_unit_program_exports) then
  1989. read_exports
  1990. else
  1991. begin
  1992. Message(parser_w_unsupported_feature);
  1993. consume(_BEGIN);
  1994. end;
  1995. end
  1996. else
  1997. begin
  1998. case idtoken of
  1999. _RESOURCESTRING:
  2000. begin
  2001. { m_class is needed, because the resourcestring
  2002. loading is in the ObjPas unit }
  2003. { if (m_class in current_settings.modeswitches) then}
  2004. resourcestring_dec
  2005. { else
  2006. break;}
  2007. end;
  2008. _OPERATOR:
  2009. begin
  2010. if is_classdef then
  2011. begin
  2012. read_proc(is_classdef,nil);
  2013. is_classdef:=false;
  2014. end
  2015. else
  2016. break;
  2017. end;
  2018. _PROPERTY:
  2019. begin
  2020. if (m_fpc in current_settings.modeswitches) then
  2021. property_dec
  2022. else
  2023. break;
  2024. end;
  2025. else
  2026. break;
  2027. end;
  2028. end;
  2029. end;
  2030. until false;
  2031. { add implementations for synthetic method declarations added by
  2032. the compiler (not for unit/program init functions, their localst
  2033. is the staticst -> would duplicate the work done in pmodules) }
  2034. if current_procinfo.procdef.localst.symtabletype=localsymtable then
  2035. add_synthetic_method_implementations(current_procinfo.procdef.localst);
  2036. { check for incomplete class definitions, this is only required
  2037. for fpc modes }
  2038. if (m_fpc in current_settings.modeswitches) then
  2039. current_procinfo.procdef.localst.SymList.ForEachCall(@check_forward_class,nil);
  2040. end;
  2041. procedure read_interface_declarations;
  2042. begin
  2043. repeat
  2044. case token of
  2045. _CONST :
  2046. const_dec;
  2047. _TYPE :
  2048. type_dec;
  2049. _VAR :
  2050. var_dec;
  2051. _THREADVAR :
  2052. threadvar_dec;
  2053. _FUNCTION,
  2054. _PROCEDURE,
  2055. _OPERATOR :
  2056. read_proc(false,nil);
  2057. else
  2058. begin
  2059. case idtoken of
  2060. _RESOURCESTRING :
  2061. resourcestring_dec;
  2062. _PROPERTY:
  2063. begin
  2064. if (m_fpc in current_settings.modeswitches) then
  2065. property_dec
  2066. else
  2067. break;
  2068. end;
  2069. else
  2070. break;
  2071. end;
  2072. end;
  2073. end;
  2074. until false;
  2075. { check for incomplete class definitions, this is only required
  2076. for fpc modes }
  2077. if (m_fpc in current_settings.modeswitches) then
  2078. symtablestack.top.SymList.ForEachCall(@check_forward_class,nil);
  2079. end;
  2080. {****************************************************************************
  2081. SPECIALIZATION BODY GENERATION
  2082. ****************************************************************************}
  2083. procedure specialize_objectdefs(p:TObject;arg:pointer);
  2084. var
  2085. oldcurrent_filepos : tfileposinfo;
  2086. specobj : tabstractrecorddef;
  2087. state : tspecializationstate;
  2088. procedure process_abstractrecorddef(def:tabstractrecorddef);
  2089. var
  2090. i : longint;
  2091. hp : tdef;
  2092. hmodule : tmodule;
  2093. begin
  2094. hmodule:=find_module_from_symtable(def.genericdef.owner);
  2095. if hmodule=nil then
  2096. internalerror(201202041);
  2097. for i:=0 to def.symtable.DefList.Count-1 do
  2098. begin
  2099. hp:=tdef(def.symtable.DefList[i]);
  2100. if hp.typ=procdef then
  2101. begin
  2102. { only generate the code if we need a body }
  2103. if assigned(tprocdef(hp).struct) and not tprocdef(hp).forwarddef then
  2104. continue;
  2105. if assigned(tprocdef(hp).genericdef) and
  2106. (tprocdef(hp).genericdef.typ=procdef) and
  2107. assigned(tprocdef(tprocdef(hp).genericdef).generictokenbuf) then
  2108. begin
  2109. oldcurrent_filepos:=current_filepos;
  2110. current_filepos:=tprocdef(tprocdef(hp).genericdef).fileinfo;
  2111. { use the index the module got from the current compilation process }
  2112. current_filepos.moduleindex:=hmodule.unit_index;
  2113. current_tokenpos:=current_filepos;
  2114. current_scanner.startreplaytokens(tprocdef(tprocdef(hp).genericdef).generictokenbuf);
  2115. read_proc_body(nil,tprocdef(hp));
  2116. current_filepos:=oldcurrent_filepos;
  2117. end
  2118. { synthetic routines will be implemented afterwards }
  2119. else if tprocdef(hp).synthetickind=tsk_none then
  2120. MessagePos1(tprocdef(hp).fileinfo,sym_e_forward_not_resolved,tprocdef(hp).fullprocname(false));
  2121. end
  2122. else
  2123. if hp.typ in [objectdef,recorddef] then
  2124. { generate code for subtypes as well }
  2125. process_abstractrecorddef(tabstractrecorddef(hp));
  2126. end;
  2127. end;
  2128. begin
  2129. if not((tsym(p).typ=typesym) and
  2130. (ttypesym(p).typedef.typesym=tsym(p)) and
  2131. (ttypesym(p).typedef.typ in [objectdef,recorddef]) and
  2132. (df_specialization in ttypesym(p).typedef.defoptions)
  2133. ) then
  2134. exit;
  2135. { Setup symtablestack a definition time }
  2136. specobj:=tabstractrecorddef(ttypesym(p).typedef);
  2137. if not (is_class_or_object(specobj) or is_record(specobj) or is_javaclass(specobj)) then
  2138. exit;
  2139. specialization_init(specobj.genericdef,state);
  2140. { procedure definitions for classes or objects }
  2141. process_abstractrecorddef(specobj);
  2142. specialization_done(state);
  2143. end;
  2144. procedure generate_specialization_procs;
  2145. begin
  2146. if assigned(current_module.globalsymtable) then
  2147. current_module.globalsymtable.SymList.WhileEachCall(@specialize_objectdefs,nil);
  2148. if assigned(current_module.localsymtable) then
  2149. current_module.localsymtable.SymList.WhileEachCall(@specialize_objectdefs,nil);
  2150. end;
  2151. end.