pstatmnt.pas 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Does the parsing of the statements
  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 pstatmnt;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. tokens,node;
  22. function statement_block(starttoken : ttoken) : tnode;
  23. { reads an assembler block }
  24. function assembler_block : tnode;
  25. implementation
  26. uses
  27. { common }
  28. cutils,cclasses,
  29. { global }
  30. globtype,globals,verbose,constexp,
  31. systems,
  32. { aasm }
  33. cpubase,aasmbase,aasmtai,aasmdata,
  34. { symtable }
  35. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  36. paramgr,symutil,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nutils,ngenutil,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,pexpr,
  43. { codegen }
  44. procinfo,cgbase,
  45. { assembler reader }
  46. rabase,
  47. { wide- and unicodestrings}
  48. widestr
  49. ;
  50. function statement : tnode;forward;
  51. function if_statement : tnode;
  52. var
  53. ex,if_a,else_a : tnode;
  54. begin
  55. consume(_IF);
  56. ex:=comp_expr(true,false);
  57. consume(_THEN);
  58. if token<>_ELSE then
  59. if_a:=statement
  60. else
  61. if_a:=nil;
  62. if try_to_consume(_ELSE) then
  63. else_a:=statement
  64. else
  65. else_a:=nil;
  66. result:=cifnode.create(ex,if_a,else_a);
  67. end;
  68. { creates a block (list) of statements, til the next END token }
  69. function statements_til_end : tnode;
  70. var
  71. first,last : tstatementnode;
  72. begin
  73. first:=nil;
  74. while token<>_END do
  75. begin
  76. if first=nil then
  77. begin
  78. last:=cstatementnode.create(statement,nil);
  79. first:=last;
  80. end
  81. else
  82. begin
  83. last.right:=cstatementnode.create(statement,nil);
  84. last:=tstatementnode(last.right);
  85. end;
  86. if not try_to_consume(_SEMICOLON) then
  87. break;
  88. consume_emptystats;
  89. end;
  90. consume(_END);
  91. statements_til_end:=cblocknode.create(first);
  92. end;
  93. function case_statement : tnode;
  94. var
  95. casedef : tdef;
  96. caseexpr,p : tnode;
  97. blockid : longint;
  98. hl1,hl2 : TConstExprInt;
  99. sl1,sl2 : tstringconstnode;
  100. casedeferror, caseofstring : boolean;
  101. casenode : tcasenode;
  102. begin
  103. consume(_CASE);
  104. caseexpr:=comp_expr(true,false);
  105. { determines result type }
  106. do_typecheckpass(caseexpr);
  107. { variants must be accepted, but first they must be converted to integer }
  108. if caseexpr.resultdef.typ=variantdef then
  109. begin
  110. caseexpr:=ctypeconvnode.create_internal(caseexpr,sinttype);
  111. do_typecheckpass(caseexpr);
  112. end;
  113. set_varstate(caseexpr,vs_read,[vsf_must_be_valid]);
  114. casedeferror:=false;
  115. casedef:=caseexpr.resultdef;
  116. { case of string must be rejected in delphi-, }
  117. { tp7/bp7-, mac-compatibility modes. }
  118. caseofstring :=
  119. ([m_delphi, m_mac, m_tp7] * current_settings.modeswitches = []) and
  120. is_string(casedef);
  121. if (not assigned(casedef)) or
  122. ( not(is_ordinal(casedef)) and (not caseofstring) ) then
  123. begin
  124. CGMessage(type_e_ordinal_or_string_expr_expected);
  125. { create a correct tree }
  126. caseexpr.free;
  127. caseexpr:=cordconstnode.create(0,u32inttype,false);
  128. { set error flag so no rangechecks are done }
  129. casedeferror:=true;
  130. end;
  131. { Create casenode }
  132. casenode:=ccasenode.create(caseexpr);
  133. consume(_OF);
  134. { Parse all case blocks }
  135. blockid:=0;
  136. repeat
  137. { maybe an instruction has more case labels }
  138. repeat
  139. p:=expr(true);
  140. if is_widechar(casedef) then
  141. begin
  142. if (p.nodetype=rangen) then
  143. begin
  144. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  145. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  146. do_typecheckpass(trangenode(p).left);
  147. do_typecheckpass(trangenode(p).right);
  148. end
  149. else
  150. begin
  151. p:=ctypeconvnode.create(p,cwidechartype);
  152. do_typecheckpass(p);
  153. end;
  154. end
  155. else
  156. begin
  157. if is_char(casedef) and is_widechar(p.resultdef) then
  158. begin
  159. if (p.nodetype=ordconstn) then
  160. begin
  161. p:=ctypeconvnode.create(p,cansichartype);
  162. do_typecheckpass(p);
  163. end
  164. else if (p.nodetype=rangen) then
  165. begin
  166. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cansichartype);
  167. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cansichartype);
  168. do_typecheckpass(trangenode(p).left);
  169. do_typecheckpass(trangenode(p).right);
  170. end;
  171. end;
  172. end;
  173. hl1:=0;
  174. hl2:=0;
  175. sl1:=nil;
  176. sl2:=nil;
  177. if (p.nodetype=rangen) then
  178. begin
  179. { type check for string case statements }
  180. if caseofstring and
  181. is_conststring_or_constcharnode(trangenode(p).left) and
  182. is_conststring_or_constcharnode(trangenode(p).right) then
  183. begin
  184. { we need stringconstnodes, even if expression contains single chars }
  185. sl1 := get_string_value(trangenode(p).left, tstringdef(casedef));
  186. sl2 := get_string_value(trangenode(p).right, tstringdef(casedef));
  187. if sl1.fullcompare(sl2) > 0 then
  188. CGMessage(parser_e_case_lower_less_than_upper_bound);
  189. end
  190. { type checking for ordinal case statements }
  191. else if (not caseofstring) and
  192. is_subequal(casedef, trangenode(p).left.resultdef) and
  193. is_subequal(casedef, trangenode(p).right.resultdef) then
  194. begin
  195. hl1:=get_ordinal_value(trangenode(p).left);
  196. hl2:=get_ordinal_value(trangenode(p).right);
  197. if hl1>hl2 then
  198. CGMessage(parser_e_case_lower_less_than_upper_bound);
  199. if not casedeferror then
  200. begin
  201. testrange(casedef,hl1,false,false);
  202. testrange(casedef,hl2,false,false);
  203. end;
  204. end
  205. else
  206. CGMessage(parser_e_case_mismatch);
  207. if caseofstring then
  208. casenode.addlabel(blockid,sl1,sl2)
  209. else
  210. casenode.addlabel(blockid,hl1,hl2);
  211. end
  212. else
  213. begin
  214. { type check for string case statements }
  215. if (caseofstring and (not is_conststring_or_constcharnode(p))) or
  216. { type checking for ordinal case statements }
  217. ((not caseofstring) and (not is_subequal(casedef, p.resultdef))) then
  218. CGMessage(parser_e_case_mismatch);
  219. if caseofstring then
  220. begin
  221. sl1:=get_string_value(p, tstringdef(casedef));
  222. casenode.addlabel(blockid,sl1,sl1);
  223. end
  224. else
  225. begin
  226. hl1:=get_ordinal_value(p);
  227. if not casedeferror then
  228. testrange(casedef,hl1,false,false);
  229. casenode.addlabel(blockid,hl1,hl1);
  230. end;
  231. end;
  232. p.free;
  233. sl1.free;
  234. sl2.free;
  235. if token=_COMMA then
  236. consume(_COMMA)
  237. else
  238. break;
  239. until false;
  240. consume(_COLON);
  241. { add instruction block }
  242. casenode.addblock(blockid,statement);
  243. { next block }
  244. inc(blockid);
  245. if not(token in [_ELSE,_OTHERWISE,_END]) then
  246. consume(_SEMICOLON);
  247. until (token in [_ELSE,_OTHERWISE,_END]);
  248. if (token in [_ELSE,_OTHERWISE]) then
  249. begin
  250. if not try_to_consume(_ELSE) then
  251. consume(_OTHERWISE);
  252. casenode.addelseblock(statements_til_end);
  253. end
  254. else
  255. consume(_END);
  256. result:=casenode;
  257. end;
  258. function repeat_statement : tnode;
  259. var
  260. first,last,p_e : tnode;
  261. begin
  262. consume(_REPEAT);
  263. first:=nil;
  264. while token<>_UNTIL do
  265. begin
  266. if first=nil then
  267. begin
  268. last:=cstatementnode.create(statement,nil);
  269. first:=last;
  270. end
  271. else
  272. begin
  273. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  274. last:=tstatementnode(last).right;
  275. end;
  276. if not try_to_consume(_SEMICOLON) then
  277. break;
  278. consume_emptystats;
  279. end;
  280. consume(_UNTIL);
  281. first:=cblocknode.create(first);
  282. p_e:=comp_expr(true,false);
  283. result:=cwhilerepeatnode.create(p_e,first,false,true);
  284. end;
  285. function while_statement : tnode;
  286. var
  287. p_e,p_a : tnode;
  288. begin
  289. consume(_WHILE);
  290. p_e:=comp_expr(true,false);
  291. consume(_DO);
  292. p_a:=statement;
  293. result:=cwhilerepeatnode.create(p_e,p_a,true,false);
  294. end;
  295. function for_statement : tnode;
  296. procedure check_range(hp:tnode; fordef: tdef);
  297. begin
  298. if (hp.nodetype=ordconstn) and
  299. (fordef.typ<>errordef) then
  300. testrange(fordef,tordconstnode(hp).value,false,true);
  301. end;
  302. function for_loop_create(hloopvar: tnode): tnode;
  303. var
  304. hp,
  305. hblock,
  306. hto,hfrom : tnode;
  307. backward : boolean;
  308. loopvarsym : tabstractvarsym;
  309. begin
  310. { Check loop variable }
  311. loopvarsym:=nil;
  312. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  313. if not(is_ordinal(hloopvar.resultdef))
  314. {$ifndef cpu64bitaddr}
  315. or is_64bitint(hloopvar.resultdef)
  316. {$endif not cpu64bitaddr}
  317. then
  318. MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
  319. hp:=hloopvar;
  320. while assigned(hp) and
  321. (
  322. { record/object fields and array elements are allowed }
  323. { in tp7 mode only }
  324. (
  325. (m_tp7 in current_settings.modeswitches) and
  326. (
  327. ((hp.nodetype=subscriptn) and
  328. ((tsubscriptnode(hp).left.resultdef.typ=recorddef) or
  329. is_object(tsubscriptnode(hp).left.resultdef))
  330. ) or
  331. { constant array index }
  332. (
  333. (hp.nodetype=vecn) and
  334. is_constintnode(tvecnode(hp).right)
  335. )
  336. )
  337. ) or
  338. { equal typeconversions }
  339. (
  340. (hp.nodetype=typeconvn) and
  341. (ttypeconvnode(hp).convtype=tc_equal)
  342. )
  343. ) do
  344. begin
  345. { Use the recordfield for loopvarsym }
  346. if not assigned(loopvarsym) and
  347. (hp.nodetype=subscriptn) then
  348. loopvarsym:=tsubscriptnode(hp).vs;
  349. hp:=tunarynode(hp).left;
  350. end;
  351. if assigned(hp) and
  352. (hp.nodetype=loadn) then
  353. begin
  354. case tloadnode(hp).symtableentry.typ of
  355. staticvarsym,
  356. localvarsym,
  357. paravarsym :
  358. begin
  359. { we need a simple loadn:
  360. 1. The load must be in a global symtable or
  361. in the same level as the para of the current proc.
  362. 2. value variables (no const,out or var)
  363. 3. No threadvar, readonly or typedconst
  364. }
  365. if (
  366. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  367. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  368. ) and
  369. (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_value) and
  370. ([vo_is_thread_var,vo_is_typed_const] * tabstractvarsym(tloadnode(hp).symtableentry).varoptions=[]) then
  371. begin
  372. { Assigning for-loop variable is only allowed in tp7 and macpas }
  373. if ([m_tp7,m_mac] * current_settings.modeswitches = []) then
  374. begin
  375. if not assigned(loopvarsym) then
  376. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  377. include(loopvarsym.varoptions,vo_is_loop_counter);
  378. end;
  379. end
  380. else
  381. begin
  382. { Typed const is allowed in tp7 }
  383. if not(m_tp7 in current_settings.modeswitches) or
  384. not(vo_is_typed_const in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
  385. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  386. end;
  387. end;
  388. else
  389. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  390. end;
  391. end
  392. else
  393. MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
  394. hfrom:=comp_expr(true,false);
  395. if try_to_consume(_DOWNTO) then
  396. backward:=true
  397. else
  398. begin
  399. consume(_TO);
  400. backward:=false;
  401. end;
  402. hto:=comp_expr(true,false);
  403. consume(_DO);
  404. { Check if the constants fit in the range }
  405. check_range(hfrom,hloopvar.resultdef);
  406. check_range(hto,hloopvar.resultdef);
  407. { first set the varstate for from and to, so
  408. uses of loopvar in those expressions will also
  409. trigger a warning when it is not used yet. This
  410. needs to be done before the instruction block is
  411. parsed to have a valid hloopvar }
  412. typecheckpass(hfrom);
  413. set_varstate(hfrom,vs_read,[vsf_must_be_valid]);
  414. typecheckpass(hto);
  415. set_varstate(hto,vs_read,[vsf_must_be_valid]);
  416. typecheckpass(hloopvar);
  417. { in two steps, because vs_readwritten may turn on vsf_must_be_valid }
  418. { for some subnodes }
  419. set_varstate(hloopvar,vs_written,[]);
  420. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  421. { ... now the instruction block }
  422. hblock:=statement;
  423. { variable is not used for loop counter anymore }
  424. if assigned(loopvarsym) then
  425. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  426. result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
  427. end;
  428. function for_in_loop_create(hloopvar: tnode): tnode;
  429. var
  430. expr: tnode;
  431. begin
  432. expr:=comp_expr(true,false);
  433. consume(_DO);
  434. set_varstate(hloopvar,vs_written,[]);
  435. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  436. result:=create_for_in_loop(hloopvar,statement,expr);
  437. expr.free;
  438. end;
  439. var
  440. hloopvar: tnode;
  441. begin
  442. { parse loop header }
  443. consume(_FOR);
  444. hloopvar:=factor(false,false);
  445. valid_for_loopvar(hloopvar,true);
  446. if try_to_consume(_ASSIGNMENT) then
  447. result:=for_loop_create(hloopvar)
  448. else if try_to_consume(_IN) then
  449. result:=for_in_loop_create(hloopvar)
  450. else
  451. consume(_ASSIGNMENT); // fail
  452. end;
  453. function _with_statement : tnode;
  454. var
  455. p : tnode;
  456. i : longint;
  457. st : TSymtable;
  458. newblock : tblocknode;
  459. newstatement : tstatementnode;
  460. calltempnode,
  461. tempnode : ttempcreatenode;
  462. valuenode,
  463. hp,
  464. refnode : tnode;
  465. hdef : tdef;
  466. helperdef : tobjectdef;
  467. hasimplicitderef : boolean;
  468. withsymtablelist : TFPObjectList;
  469. procedure pushobjchild(withdef,obj:tobjectdef);
  470. var
  471. parenthelperdef : tobjectdef;
  472. begin
  473. if not assigned(obj) then
  474. exit;
  475. pushobjchild(withdef,obj.childof);
  476. { we need to look for helpers that were defined for the parent
  477. class as well }
  478. search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
  479. { push the symtables of the helper's parents in reverse order }
  480. if assigned(parenthelperdef) then
  481. pushobjchild(withdef,parenthelperdef.childof);
  482. { keep the original tobjectdef as owner, because that is used for
  483. visibility of the symtable }
  484. st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
  485. symtablestack.push(st);
  486. withsymtablelist.add(st);
  487. { push the symtable of the helper }
  488. if assigned(parenthelperdef) then
  489. begin
  490. st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
  491. symtablestack.push(st);
  492. withsymtablelist.add(st);
  493. end;
  494. end;
  495. begin
  496. p:=comp_expr(true,false);
  497. do_typecheckpass(p);
  498. if (p.nodetype=vecn) and
  499. (nf_memseg in p.flags) then
  500. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  501. { "with procvar" can never mean anything, so always try
  502. to call it in case it returns a record/object/... }
  503. maybe_call_procvar(p,false);
  504. if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) or
  505. ((p.resultdef.typ=undefineddef) and (df_generic in current_procinfo.procdef.defoptions)) then
  506. begin
  507. newblock:=nil;
  508. valuenode:=nil;
  509. tempnode:=nil;
  510. { ignore nodes that don't add instructions in the tree }
  511. hp:=p;
  512. while { equal type conversions }
  513. (
  514. (hp.nodetype=typeconvn) and
  515. (ttypeconvnode(hp).convtype=tc_equal)
  516. ) or
  517. { constant array index }
  518. (
  519. (hp.nodetype=vecn) and
  520. (tvecnode(hp).right.nodetype=ordconstn)
  521. ) do
  522. hp:=tunarynode(hp).left;
  523. if (hp.nodetype=loadn) and
  524. (
  525. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  526. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  527. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  528. ) and
  529. { MacPas objects are mapped to classes, and the MacPas compilers
  530. interpret with-statements with MacPas objects the same way
  531. as records (the object referenced by the with-statement
  532. must remain constant)
  533. }
  534. not(is_class(hp.resultdef) and
  535. (m_mac in current_settings.modeswitches)) then
  536. begin
  537. { simple load, we can reference direct }
  538. refnode:=p;
  539. end
  540. else
  541. begin
  542. calltempnode:=nil;
  543. { complex load, load in temp first }
  544. newblock:=internalstatements(newstatement);
  545. { when we can't take the address of p, load it in a temp }
  546. { since we may need its address later on }
  547. if not valid_for_addr(p,false) then
  548. begin
  549. calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
  550. addstatement(newstatement,calltempnode);
  551. addstatement(newstatement,cassignmentnode.create(
  552. ctemprefnode.create(calltempnode),
  553. p));
  554. p:=ctemprefnode.create(calltempnode);
  555. typecheckpass(p);
  556. end;
  557. { several object types have implicit dereferencing }
  558. { is_implicit_pointer_object_type() returns true for records
  559. on the JVM target because they are implemented as classes
  560. there, but we definitely have to take their address here
  561. since otherwise a deep copy is made and changes are made to
  562. this copy rather than to the original one }
  563. hasimplicitderef:=
  564. (is_implicit_pointer_object_type(p.resultdef) or
  565. (p.resultdef.typ=classrefdef)) and
  566. not((target_info.system in systems_jvm) and
  567. ((p.resultdef.typ=recorddef) or
  568. is_object(p.resultdef)));
  569. if hasimplicitderef then
  570. hdef:=p.resultdef
  571. else
  572. hdef:=tpointerdef.create(p.resultdef);
  573. { load address of the value in a temp }
  574. tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
  575. typecheckpass(tnode(tempnode));
  576. valuenode:=p;
  577. refnode:=ctemprefnode.create(tempnode);
  578. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  579. { add address call for valuenode and deref for refnode if this
  580. is not done implicitly }
  581. if not hasimplicitderef then
  582. begin
  583. valuenode:=caddrnode.create_internal_nomark(valuenode);
  584. include(valuenode.flags,nf_typedaddr);
  585. refnode:=cderefnode.create(refnode);
  586. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  587. end;
  588. addstatement(newstatement,tempnode);
  589. addstatement(newstatement,cassignmentnode.create(
  590. ctemprefnode.create(tempnode),
  591. valuenode));
  592. typecheckpass(refnode);
  593. end;
  594. { Note: the symtable of the helper is pushed after the following
  595. "case", the symtables of the helper's parents are passed in
  596. the "case" branches }
  597. withsymtablelist:=TFPObjectList.create(true);
  598. case p.resultdef.typ of
  599. objectdef :
  600. begin
  601. { do we have a helper for this type? }
  602. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  603. { push symtables of all parents in reverse order }
  604. pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
  605. { push symtables of all parents of the helper in reverse order }
  606. if assigned(helperdef) then
  607. pushobjchild(helperdef,helperdef.childof);
  608. { push object symtable }
  609. st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
  610. symtablestack.push(st);
  611. withsymtablelist.add(st);
  612. end;
  613. classrefdef :
  614. begin
  615. { do we have a helper for this type? }
  616. search_last_objectpascal_helper(tobjectdef(tclassrefdef(p.resultdef).pointeddef),current_structdef,helperdef);
  617. { push symtables of all parents in reverse order }
  618. pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
  619. { push symtables of all parents of the helper in reverse order }
  620. if assigned(helperdef) then
  621. pushobjchild(helperdef,helperdef.childof);
  622. { push object symtable }
  623. st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
  624. symtablestack.push(st);
  625. withsymtablelist.add(st);
  626. end;
  627. recorddef :
  628. begin
  629. { do we have a helper for this type? }
  630. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  631. { push symtables of all parents of the helper in reverse order }
  632. if assigned(helperdef) then
  633. pushobjchild(helperdef,helperdef.childof);
  634. { push record symtable }
  635. st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
  636. symtablestack.push(st);
  637. withsymtablelist.add(st);
  638. end;
  639. undefineddef :
  640. begin
  641. if not(df_generic in current_procinfo.procdef.defoptions) then
  642. internalerror(2012122802);
  643. helperdef:=nil;
  644. { push record symtable }
  645. st:=twithsymtable.create(p.resultdef,nil,refnode);
  646. symtablestack.push(st);
  647. withsymtablelist.add(st);
  648. end;
  649. else
  650. internalerror(200601271);
  651. end;
  652. { push helper symtable }
  653. if assigned(helperdef) then
  654. begin
  655. st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
  656. symtablestack.push(st);
  657. withsymtablelist.add(st);
  658. end;
  659. if try_to_consume(_COMMA) then
  660. p:=_with_statement()
  661. else
  662. begin
  663. consume(_DO);
  664. if token<>_SEMICOLON then
  665. p:=statement
  666. else
  667. p:=cnothingnode.create;
  668. end;
  669. { remove symtables in reverse order from the stack }
  670. for i:=withsymtablelist.count-1 downto 0 do
  671. symtablestack.pop(TSymtable(withsymtablelist[i]));
  672. withsymtablelist.free;
  673. // p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refnode);
  674. { Finalize complex withnode with destroy of temp }
  675. if assigned(newblock) then
  676. begin
  677. addstatement(newstatement,p);
  678. if assigned(tempnode) then
  679. addstatement(newstatement,ctempdeletenode.create(tempnode));
  680. if assigned(calltempnode) then
  681. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  682. p:=newblock;
  683. end;
  684. result:=p;
  685. end
  686. else
  687. begin
  688. p.free;
  689. Message1(parser_e_false_with_expr,p.resultdef.GetTypeName);
  690. { try to recover from error }
  691. if try_to_consume(_COMMA) then
  692. begin
  693. hp:=_with_statement();
  694. if (hp=nil) then; { remove warning about unused }
  695. end
  696. else
  697. begin
  698. consume(_DO);
  699. { ignore all }
  700. if token<>_SEMICOLON then
  701. statement;
  702. end;
  703. result:=nil;
  704. end;
  705. end;
  706. function with_statement : tnode;
  707. begin
  708. consume(_WITH);
  709. with_statement:=_with_statement();
  710. end;
  711. function raise_statement : tnode;
  712. var
  713. p,pobj,paddr,pframe : tnode;
  714. begin
  715. pobj:=nil;
  716. paddr:=nil;
  717. pframe:=nil;
  718. consume(_RAISE);
  719. if not(token in endtokens) then
  720. begin
  721. { object }
  722. pobj:=comp_expr(true,false);
  723. if try_to_consume(_AT) then
  724. begin
  725. paddr:=comp_expr(true,false);
  726. if try_to_consume(_COMMA) then
  727. pframe:=comp_expr(true,false);
  728. end;
  729. end
  730. else
  731. begin
  732. if (block_type<>bt_except) then
  733. Message(parser_e_no_reraise_possible);
  734. end;
  735. p:=craisenode.create(pobj,paddr,pframe);
  736. raise_statement:=p;
  737. end;
  738. function try_statement : tnode;
  739. var
  740. p_try_block,p_finally_block,first,last,
  741. p_default,p_specific,hp : tnode;
  742. ot : tDef;
  743. sym : tlocalvarsym;
  744. old_block_type : tblock_type;
  745. excepTSymtable : TSymtable;
  746. objname,objrealname : TIDString;
  747. srsym : tsym;
  748. srsymtable : TSymtable;
  749. t:ttoken;
  750. unit_found:boolean;
  751. oldcurrent_exceptblock: integer;
  752. begin
  753. p_default:=nil;
  754. p_specific:=nil;
  755. { read statements to try }
  756. consume(_TRY);
  757. first:=nil;
  758. inc(exceptblockcounter);
  759. oldcurrent_exceptblock := current_exceptblock;
  760. current_exceptblock := exceptblockcounter;
  761. old_block_type := block_type;
  762. block_type := bt_body;
  763. while (token<>_FINALLY) and (token<>_EXCEPT) do
  764. begin
  765. if first=nil then
  766. begin
  767. last:=cstatementnode.create(statement,nil);
  768. first:=last;
  769. end
  770. else
  771. begin
  772. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  773. last:=tstatementnode(last).right;
  774. end;
  775. if not try_to_consume(_SEMICOLON) then
  776. break;
  777. consume_emptystats;
  778. end;
  779. p_try_block:=cblocknode.create(first);
  780. if try_to_consume(_FINALLY) then
  781. begin
  782. inc(exceptblockcounter);
  783. current_exceptblock := exceptblockcounter;
  784. p_finally_block:=statements_til_end;
  785. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  786. end
  787. else
  788. begin
  789. consume(_EXCEPT);
  790. block_type:=bt_except;
  791. inc(exceptblockcounter);
  792. current_exceptblock := exceptblockcounter;
  793. ot:=generrordef;
  794. p_specific:=nil;
  795. if (idtoken=_ON) then
  796. { catch specific exceptions }
  797. begin
  798. repeat
  799. consume(_ON);
  800. if token=_ID then
  801. begin
  802. objname:=pattern;
  803. objrealname:=orgpattern;
  804. { can't use consume_sym here, because we need already
  805. to check for the colon }
  806. searchsym(objname,srsym,srsymtable);
  807. consume(_ID);
  808. { is a explicit name for the exception given ? }
  809. if try_to_consume(_COLON) then
  810. begin
  811. consume_sym(srsym,srsymtable);
  812. if (srsym.typ=typesym) and
  813. (is_class(ttypesym(srsym).typedef) or
  814. is_javaclass(ttypesym(srsym).typedef)) then
  815. begin
  816. ot:=ttypesym(srsym).typedef;
  817. sym:=tlocalvarsym.create(objrealname,vs_value,ot,[]);
  818. end
  819. else
  820. begin
  821. sym:=tlocalvarsym.create(objrealname,vs_value,generrordef,[]);
  822. if (srsym.typ=typesym) then
  823. Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
  824. else
  825. Message1(type_e_class_type_expected,ot.typename);
  826. end;
  827. end
  828. else
  829. begin
  830. { check if type is valid, must be done here because
  831. with "e: Exception" the e is not necessary }
  832. { support unit.identifier }
  833. unit_found:=try_consume_unitsym(srsym,srsymtable,t,false);
  834. if srsym=nil then
  835. begin
  836. identifier_not_found(orgpattern);
  837. srsym:=generrorsym;
  838. end;
  839. if unit_found then
  840. consume(t);
  841. { check if type is valid, must be done here because
  842. with "e: Exception" the e is not necessary }
  843. if (srsym.typ=typesym) and
  844. (is_class(ttypesym(srsym).typedef) or
  845. is_javaclass(ttypesym(srsym).typedef)) then
  846. ot:=ttypesym(srsym).typedef
  847. else
  848. begin
  849. ot:=generrordef;
  850. if (srsym.typ=typesym) then
  851. Message1(type_e_class_type_expected,ttypesym(srsym).typedef.typename)
  852. else
  853. Message1(type_e_class_type_expected,ot.typename);
  854. end;
  855. { create dummy symbol so we don't need a special
  856. case in ncgflw, and so that we always know the
  857. type }
  858. sym:=tlocalvarsym.create('$exceptsym',vs_value,ot,[]);
  859. end;
  860. excepTSymtable:=tstt_excepTSymtable.create;
  861. excepTSymtable.insert(sym);
  862. symtablestack.push(excepTSymtable);
  863. end
  864. else
  865. consume(_ID);
  866. consume(_DO);
  867. hp:=connode.create(nil,statement);
  868. if ot.typ=errordef then
  869. begin
  870. hp.free;
  871. hp:=cerrornode.create;
  872. end;
  873. if p_specific=nil then
  874. begin
  875. last:=hp;
  876. p_specific:=last;
  877. end
  878. else
  879. begin
  880. tonnode(last).left:=hp;
  881. last:=tonnode(last).left;
  882. end;
  883. { set the informations }
  884. { only if the creation of the onnode was succesful, it's possible }
  885. { that last and hp are errornodes (JM) }
  886. if last.nodetype = onn then
  887. begin
  888. tonnode(last).excepttype:=tobjectdef(ot);
  889. tonnode(last).excepTSymtable:=excepTSymtable;
  890. end;
  891. { remove exception symtable }
  892. if assigned(excepTSymtable) then
  893. begin
  894. symtablestack.pop(excepTSymtable);
  895. if last.nodetype <> onn then
  896. excepTSymtable.free;
  897. end;
  898. if not try_to_consume(_SEMICOLON) then
  899. break;
  900. consume_emptystats;
  901. until (token in [_END,_ELSE]);
  902. if try_to_consume(_ELSE) then
  903. begin
  904. { catch the other exceptions }
  905. p_default:=statements_til_end;
  906. end
  907. else
  908. consume(_END);
  909. end
  910. else
  911. begin
  912. { catch all exceptions }
  913. p_default:=statements_til_end;
  914. end;
  915. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  916. end;
  917. block_type:=old_block_type;
  918. current_exceptblock := oldcurrent_exceptblock;
  919. end;
  920. function _asm_statement : tnode;
  921. var
  922. asmstat : tasmnode;
  923. Marker : tai;
  924. reg : tregister;
  925. asmreader : tbaseasmreader;
  926. entrypos : tfileposinfo;
  927. begin
  928. Inside_asm_statement:=true;
  929. if assigned(asmmodeinfos[current_settings.asmmode]) then
  930. begin
  931. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  932. entrypos:=current_filepos;
  933. asmstat:=casmnode.create(asmreader.assemble as TAsmList);
  934. asmstat.fileinfo:=entrypos;
  935. asmreader.free;
  936. end
  937. else
  938. Message(parser_f_assembler_reader_not_supported);
  939. { Mark procedure that it has assembler blocks }
  940. include(current_procinfo.flags,pi_has_assembler_block);
  941. { Read first the _ASM statement }
  942. consume(_ASM);
  943. { END is read, got a list of changed registers? }
  944. if try_to_consume(_LECKKLAMMER) then
  945. begin
  946. {$ifdef cpunofpu}
  947. asmstat.used_regs_fpu:=[0..first_int_imreg-1];
  948. {$else cpunofpu}
  949. asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
  950. {$endif cpunofpu}
  951. if token<>_RECKKLAMMER then
  952. begin
  953. if po_assembler in current_procinfo.procdef.procoptions then
  954. Message(parser_w_register_list_ignored);
  955. repeat
  956. { it's possible to specify the modified registers }
  957. reg:=std_regnum_search(lower(cstringpattern));
  958. if reg<>NR_NO then
  959. begin
  960. if (getregtype(reg)=R_INTREGISTER) and not(po_assembler in current_procinfo.procdef.procoptions) then
  961. include(asmstat.used_regs_int,getsupreg(reg));
  962. end
  963. else
  964. Message(asmr_e_invalid_register);
  965. consume(_CSTRING);
  966. if not try_to_consume(_COMMA) then
  967. break;
  968. until false;
  969. end;
  970. consume(_RECKKLAMMER);
  971. end
  972. else
  973. begin
  974. asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
  975. asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
  976. end;
  977. { mark the start and the end of the assembler block
  978. this is needed for the optimizer }
  979. If Assigned(AsmStat.p_asm) Then
  980. Begin
  981. Marker := Tai_Marker.Create(mark_AsmBlockStart);
  982. AsmStat.p_asm.Insert(Marker);
  983. Marker := Tai_Marker.Create(mark_AsmBlockEnd);
  984. AsmStat.p_asm.Concat(Marker);
  985. End;
  986. Inside_asm_statement:=false;
  987. _asm_statement:=asmstat;
  988. end;
  989. function statement : tnode;
  990. var
  991. p,
  992. code : tnode;
  993. filepos : tfileposinfo;
  994. srsym : tsym;
  995. srsymtable : TSymtable;
  996. s : TIDString;
  997. begin
  998. filepos:=current_tokenpos;
  999. case token of
  1000. _GOTO :
  1001. begin
  1002. if not(cs_support_goto in current_settings.moduleswitches) then
  1003. Message(sym_e_goto_and_label_not_supported);
  1004. consume(_GOTO);
  1005. if (token<>_INTCONST) and (token<>_ID) then
  1006. begin
  1007. Message(sym_e_label_not_found);
  1008. code:=cerrornode.create;
  1009. end
  1010. else
  1011. begin
  1012. if token=_ID then
  1013. consume_sym(srsym,srsymtable)
  1014. else
  1015. begin
  1016. if token<>_INTCONST then
  1017. internalerror(201008021);
  1018. { strip leading 0's in iso mode }
  1019. if m_iso in current_settings.modeswitches then
  1020. while pattern[1]='0' do
  1021. delete(pattern,1,1);
  1022. searchsym(pattern,srsym,srsymtable);
  1023. if srsym=nil then
  1024. begin
  1025. identifier_not_found(pattern);
  1026. srsym:=generrorsym;
  1027. srsymtable:=nil;
  1028. end;
  1029. consume(token);
  1030. end;
  1031. if srsym.typ<>labelsym then
  1032. begin
  1033. Message(sym_e_id_is_no_label_id);
  1034. code:=cerrornode.create;
  1035. end
  1036. else
  1037. begin
  1038. { goto outside the current scope? }
  1039. if srsym.owner<>current_procinfo.procdef.localst then
  1040. begin
  1041. { allowed? }
  1042. if not(m_non_local_goto in current_settings.modeswitches) then
  1043. Message(parser_e_goto_outside_proc);
  1044. include(current_procinfo.flags,pi_has_global_goto);
  1045. end;
  1046. code:=cgotonode.create(tlabelsym(srsym));
  1047. tgotonode(code).labelsym:=tlabelsym(srsym);
  1048. { set flag that this label is used }
  1049. tlabelsym(srsym).used:=true;
  1050. end;
  1051. end;
  1052. end;
  1053. _BEGIN :
  1054. code:=statement_block(_BEGIN);
  1055. _IF :
  1056. code:=if_statement;
  1057. _CASE :
  1058. code:=case_statement;
  1059. _REPEAT :
  1060. code:=repeat_statement;
  1061. _WHILE :
  1062. code:=while_statement;
  1063. _FOR :
  1064. code:=for_statement;
  1065. _WITH :
  1066. code:=with_statement;
  1067. _TRY :
  1068. code:=try_statement;
  1069. _RAISE :
  1070. code:=raise_statement;
  1071. { semicolons,else until and end are ignored }
  1072. _SEMICOLON,
  1073. _ELSE,
  1074. _UNTIL,
  1075. _END:
  1076. code:=cnothingnode.create;
  1077. _FAIL :
  1078. begin
  1079. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  1080. Message(parser_e_fail_only_in_constructor);
  1081. consume(_FAIL);
  1082. code:=cnodeutils.call_fail_node;
  1083. end;
  1084. _ASM :
  1085. begin
  1086. if parse_generic then
  1087. Message(parser_e_no_assembler_in_generic);
  1088. code:=_asm_statement;
  1089. end;
  1090. _EOF :
  1091. Message(scan_f_end_of_file);
  1092. else
  1093. begin
  1094. { don't typecheck yet, because that will also simplify, which may
  1095. result in not detecting certain kinds of syntax errors --
  1096. see mantis #15594 }
  1097. p:=expr(false);
  1098. { save the pattern here for latter usage, the label could be "000",
  1099. even if we read an expression, the pattern is still valid if it's really
  1100. a label (FK)
  1101. if you want to mess here, take care of
  1102. tests/webtbs/tw3546.pp
  1103. }
  1104. s:=pattern;
  1105. { When a colon follows a intconst then transform it into a label }
  1106. if (p.nodetype=ordconstn) and
  1107. try_to_consume(_COLON) then
  1108. begin
  1109. { in iso mode, 0003: is equal to 3: }
  1110. if m_iso in current_settings.modeswitches then
  1111. searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
  1112. else
  1113. searchsym(s,srsym,srsymtable);
  1114. p.free;
  1115. if assigned(srsym) and
  1116. (srsym.typ=labelsym) then
  1117. begin
  1118. if tlabelsym(srsym).defined then
  1119. Message(sym_e_label_already_defined);
  1120. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1121. begin
  1122. tlabelsym(srsym).nonlocal:=true;
  1123. exclude(current_procinfo.procdef.procoptions,po_inline);
  1124. end;
  1125. if tlabelsym(srsym).nonlocal and
  1126. (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1127. Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
  1128. tlabelsym(srsym).defined:=true;
  1129. p:=clabelnode.create(nil,tlabelsym(srsym));
  1130. tlabelsym(srsym).code:=p;
  1131. end
  1132. else
  1133. begin
  1134. Message1(sym_e_label_used_and_not_defined,s);
  1135. p:=cnothingnode.create;
  1136. end;
  1137. end;
  1138. if p.nodetype=labeln then
  1139. begin
  1140. { the pointer to the following instruction }
  1141. { isn't a very clean way }
  1142. if token in endtokens then
  1143. tlabelnode(p).left:=cnothingnode.create
  1144. else
  1145. tlabelnode(p).left:=statement();
  1146. { be sure to have left also typecheckpass }
  1147. typecheckpass(tlabelnode(p).left);
  1148. end
  1149. else
  1150. { change a load of a procvar to a call. this is also
  1151. supported in fpc mode }
  1152. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1153. maybe_call_procvar(p,false);
  1154. { blockn support because a read/write is changed into a blocknode
  1155. with a separate statement for each read/write operation (JM)
  1156. the same is true for val() if the third parameter is not 32 bit
  1157. goto nodes are created by the compiler for non local exit statements, so
  1158. include them as well
  1159. }
  1160. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1161. continuen,labeln,blockn,exitn,goton]) or
  1162. ((p.nodetype=inlinen) and
  1163. not is_void(p.resultdef)) or
  1164. ((p.nodetype=calln) and
  1165. (assigned(tcallnode(p).procdefinition)) and
  1166. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1167. Message(parser_e_illegal_expression);
  1168. if not assigned(p.resultdef) then
  1169. do_typecheckpass(p);
  1170. { Specify that we don't use the value returned by the call.
  1171. This is used for :
  1172. - dispose of temp stack space
  1173. - dispose on FPU stack
  1174. - extended syntax checking }
  1175. if (p.nodetype=calln) then
  1176. begin
  1177. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1178. { in $x- state, the function result must not be ignored }
  1179. if not(cs_extsyntax in current_settings.moduleswitches) and
  1180. not(is_void(p.resultdef)) and
  1181. { can be nil in case there was an error in the expression }
  1182. assigned(tcallnode(p).procdefinition) and
  1183. not((tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
  1184. is_object(tprocdef(tcallnode(p).procdefinition).struct)) then
  1185. Message(parser_e_illegal_expression);
  1186. end;
  1187. code:=p;
  1188. end;
  1189. end;
  1190. if assigned(code) then
  1191. begin
  1192. typecheckpass(code);
  1193. code.fileinfo:=filepos;
  1194. end;
  1195. statement:=code;
  1196. end;
  1197. function statement_block(starttoken : ttoken) : tnode;
  1198. var
  1199. first,last : tnode;
  1200. filepos : tfileposinfo;
  1201. begin
  1202. first:=nil;
  1203. filepos:=current_tokenpos;
  1204. consume(starttoken);
  1205. while not(token in [_END,_FINALIZATION]) do
  1206. begin
  1207. if first=nil then
  1208. begin
  1209. last:=cstatementnode.create(statement,nil);
  1210. first:=last;
  1211. end
  1212. else
  1213. begin
  1214. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1215. last:=tstatementnode(last).right;
  1216. end;
  1217. if (token in [_END,_FINALIZATION]) then
  1218. break
  1219. else
  1220. begin
  1221. { if no semicolon, then error and go on }
  1222. if token<>_SEMICOLON then
  1223. begin
  1224. consume(_SEMICOLON);
  1225. consume_all_until(_SEMICOLON);
  1226. end;
  1227. consume(_SEMICOLON);
  1228. end;
  1229. consume_emptystats;
  1230. end;
  1231. { don't consume the finalization token, it is consumed when
  1232. reading the finalization block, but allow it only after
  1233. an initalization ! }
  1234. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1235. consume(_END);
  1236. last:=cblocknode.create(first);
  1237. last.fileinfo:=filepos;
  1238. statement_block:=last;
  1239. end;
  1240. function assembler_block : tnode;
  1241. var
  1242. p : tnode;
  1243. {$ifndef arm}
  1244. locals : longint;
  1245. {$endif arm}
  1246. srsym : tsym;
  1247. begin
  1248. if parse_generic then
  1249. message(parser_e_no_assembler_in_generic);
  1250. { Rename the funcret so that recursive calls are possible }
  1251. if not is_void(current_procinfo.procdef.returndef) then
  1252. begin
  1253. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1254. if assigned(srsym) then
  1255. srsym.realname:='$hiddenresult';
  1256. end;
  1257. { delphi uses register calling for assembler methods }
  1258. if (m_delphi in current_settings.modeswitches) and
  1259. (po_assembler in current_procinfo.procdef.procoptions) and
  1260. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1261. current_procinfo.procdef.proccalloption:=pocall_register;
  1262. { force the asm statement }
  1263. if token<>_ASM then
  1264. consume(_ASM);
  1265. include(current_procinfo.flags,pi_is_assembler);
  1266. p:=_asm_statement;
  1267. {$if not(defined(sparc)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1268. if (po_assembler in current_procinfo.procdef.procoptions) then
  1269. begin
  1270. { set the framepointer to esp for assembler functions when the
  1271. following conditions are met:
  1272. - if the are no local variables and parameters (except the allocated result)
  1273. - no reference to the result variable (refcount<=1)
  1274. - result is not stored as parameter
  1275. - target processor has optional frame pointer save
  1276. (vm, i386, vm only currently)
  1277. }
  1278. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1279. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1280. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1281. if (locals=0) and
  1282. not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1283. (not assigned(current_procinfo.procdef.funcretsym) or
  1284. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1285. not (df_generic in current_procinfo.procdef.defoptions) and
  1286. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1287. begin
  1288. { Only need to set the framepointer, the locals will
  1289. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1290. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1291. end;
  1292. end;
  1293. {$endif not(defined(sparc)) and not(defined(arm)) and not(defined(avr))}
  1294. { Flag the result as assigned when it is returned in a
  1295. register.
  1296. }
  1297. if assigned(current_procinfo.procdef.funcretsym) and
  1298. not (df_generic in current_procinfo.procdef.defoptions) and
  1299. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1300. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1301. { because the END is already read we need to get the
  1302. last_endtoken_filepos here (PFV) }
  1303. last_endtoken_filepos:=current_tokenpos;
  1304. assembler_block:=p;
  1305. end;
  1306. end.