psub.pas 108 KB

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