pstatmnt.pas 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678
  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,aasmtai,aasmdata,aasmbase,
  34. { symtable }
  35. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  36. paramgr,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nutils,ngenutil,nbas,ncal,nmem,nset,ncnv,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,ptype,pexpr,
  43. { codegen }
  44. procinfo,cgbase,
  45. { assembler reader }
  46. rabase;
  47. function statement : tnode;forward;
  48. function if_statement : tnode;
  49. var
  50. ex,if_a,else_a : tnode;
  51. begin
  52. consume(_IF);
  53. ex:=comp_expr([ef_accept_equal]);
  54. consume(_THEN);
  55. if not(token in endtokens) then
  56. if_a:=statement
  57. else
  58. if_a:=nil;
  59. if try_to_consume(_ELSE) then
  60. else_a:=statement
  61. else
  62. else_a:=nil;
  63. result:=cifnode.create(ex,if_a,else_a);
  64. end;
  65. { creates a block (list) of statements, til the next END token }
  66. function statements_til_end : tnode;
  67. var
  68. first,last : tstatementnode;
  69. begin
  70. first:=nil;
  71. last:=nil;
  72. while token<>_END do
  73. begin
  74. if first=nil then
  75. begin
  76. last:=cstatementnode.create(statement,nil);
  77. first:=last;
  78. end
  79. else
  80. begin
  81. last.right:=cstatementnode.create(statement,nil);
  82. last:=tstatementnode(last.right);
  83. end;
  84. if not try_to_consume(_SEMICOLON) then
  85. break;
  86. consume_emptystats;
  87. end;
  88. consume(_END);
  89. statements_til_end:=cblocknode.create(first);
  90. if assigned(first) then
  91. statements_til_end.fileinfo:=first.fileinfo;
  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([ef_accept_equal]);
  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. adaptrange(casedef,hl1,false,false,cs_check_range in current_settings.localswitches);
  202. adaptrange(casedef,hl2,false,false,cs_check_range in current_settings.localswitches);
  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. adaptrange(casedef,hl1,false,false,cs_check_range in current_settings.localswitches);
  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. last:=nil;
  265. while token<>_UNTIL do
  266. begin
  267. if first=nil then
  268. begin
  269. last:=cstatementnode.create(statement,nil);
  270. first:=last;
  271. end
  272. else
  273. begin
  274. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  275. last:=tstatementnode(last).right;
  276. end;
  277. if not try_to_consume(_SEMICOLON) then
  278. break;
  279. consume_emptystats;
  280. end;
  281. consume(_UNTIL);
  282. first:=cblocknode.create(first);
  283. p_e:=comp_expr([ef_accept_equal]);
  284. result:=cwhilerepeatnode.create(p_e,first,false,true);
  285. end;
  286. function while_statement : tnode;
  287. var
  288. p_e,p_a : tnode;
  289. begin
  290. consume(_WHILE);
  291. p_e:=comp_expr([ef_accept_equal]);
  292. consume(_DO);
  293. p_a:=statement;
  294. result:=cwhilerepeatnode.create(p_e,p_a,true,false);
  295. end;
  296. { a helper function which is used both by "with" and "for-in loop" nodes }
  297. function skip_nodes_before_load(p: tnode): tnode;
  298. begin
  299. { ignore nodes that don't add instructions in the tree }
  300. while assigned(p) and
  301. { equal type conversions }
  302. (
  303. (p.nodetype=typeconvn) and
  304. (ttypeconvnode(p).convtype=tc_equal)
  305. ) or
  306. { constant array index }
  307. (
  308. (p.nodetype=vecn) and
  309. (tvecnode(p).right.nodetype=ordconstn)
  310. ) do
  311. p:=tunarynode(p).left;
  312. result:=p;
  313. end;
  314. function for_statement : tnode;
  315. procedure check_range(hp:tnode; fordef: tdef);
  316. begin
  317. if (hp.nodetype=ordconstn) and
  318. (fordef.typ<>errordef) and
  319. { the node was derived from a generic parameter so ignore range check }
  320. not(nf_generic_para in hp.flags) then
  321. adaptrange(fordef,tordconstnode(hp).value,false,false,true);
  322. end;
  323. function for_loop_create(hloopvar: tnode): tnode;
  324. var
  325. hp,
  326. hblock,
  327. hto,hfrom : tnode;
  328. backward : boolean;
  329. loopvarsym : tabstractvarsym;
  330. begin
  331. { Check loop variable }
  332. loopvarsym:=nil;
  333. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  334. if (
  335. not(is_ordinal(hloopvar.resultdef))
  336. {$if not defined(cpu64bitaddr) and not defined(cpu64bitalu)}
  337. or is_64bitint(hloopvar.resultdef)
  338. {$endif not cpu64bitaddr and not cpu64bitalu}
  339. ) and
  340. (hloopvar.resultdef.typ<>undefineddef)
  341. then
  342. begin
  343. MessagePos(hloopvar.fileinfo,type_e_ordinal_expr_expected);
  344. hloopvar.resultdef:=generrordef;
  345. end;
  346. hp:=hloopvar;
  347. while assigned(hp) and
  348. (
  349. { record/object fields and array elements are allowed }
  350. { in tp7 mode only }
  351. (
  352. (m_tp7 in current_settings.modeswitches) and
  353. (
  354. ((hp.nodetype=subscriptn) and
  355. ((tsubscriptnode(hp).left.resultdef.typ=recorddef) or
  356. is_object(tsubscriptnode(hp).left.resultdef))
  357. ) or
  358. { constant array index }
  359. (
  360. (hp.nodetype=vecn) and
  361. is_constintnode(tvecnode(hp).right)
  362. )
  363. )
  364. ) or
  365. { equal typeconversions }
  366. (
  367. (hp.nodetype=typeconvn) and
  368. (ttypeconvnode(hp).convtype=tc_equal)
  369. )
  370. ) do
  371. begin
  372. { Use the recordfield for loopvarsym }
  373. if not assigned(loopvarsym) and
  374. (hp.nodetype=subscriptn) then
  375. loopvarsym:=tsubscriptnode(hp).vs;
  376. hp:=tunarynode(hp).left;
  377. end;
  378. if assigned(hp) and
  379. (hp.nodetype=loadn) then
  380. begin
  381. case tloadnode(hp).symtableentry.typ of
  382. staticvarsym,
  383. localvarsym,
  384. paravarsym :
  385. begin
  386. { we need a simple loadn:
  387. 1. The load must be in a global symtable or
  388. in the same level as the para of the current proc.
  389. 2. value variables (no const,out or var)
  390. 3. No threadvar, readonly or typedconst
  391. }
  392. if (
  393. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  394. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  395. ) and
  396. (tabstractvarsym(tloadnode(hp).symtableentry).varspez=vs_value) and
  397. ([vo_is_thread_var,vo_is_typed_const] * tabstractvarsym(tloadnode(hp).symtableentry).varoptions=[]) then
  398. begin
  399. { Assigning for-loop variable is only allowed in tp7 and macpas }
  400. if ([m_tp7,m_mac] * current_settings.modeswitches = []) then
  401. begin
  402. if not assigned(loopvarsym) then
  403. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  404. include(loopvarsym.varoptions,vo_is_loop_counter);
  405. end;
  406. end
  407. else
  408. begin
  409. { Typed const is allowed in tp7 }
  410. if not(m_tp7 in current_settings.modeswitches) or
  411. not(vo_is_typed_const in tabstractvarsym(tloadnode(hp).symtableentry).varoptions) then
  412. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  413. end;
  414. end;
  415. else
  416. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  417. end;
  418. end
  419. else
  420. MessagePos(hloopvar.fileinfo,type_e_illegal_count_var);
  421. hfrom:=comp_expr([ef_accept_equal]);
  422. if try_to_consume(_DOWNTO) then
  423. backward:=true
  424. else
  425. begin
  426. consume(_TO);
  427. backward:=false;
  428. end;
  429. hto:=comp_expr([ef_accept_equal]);
  430. consume(_DO);
  431. { Check if the constants fit in the range }
  432. check_range(hfrom,hloopvar.resultdef);
  433. check_range(hto,hloopvar.resultdef);
  434. { first set the varstate for from and to, so
  435. uses of loopvar in those expressions will also
  436. trigger a warning when it is not used yet. This
  437. needs to be done before the instruction block is
  438. parsed to have a valid hloopvar }
  439. typecheckpass(hfrom);
  440. set_varstate(hfrom,vs_read,[vsf_must_be_valid]);
  441. typecheckpass(hto);
  442. set_varstate(hto,vs_read,[vsf_must_be_valid]);
  443. typecheckpass(hloopvar);
  444. { in two steps, because vs_readwritten may turn on vsf_must_be_valid }
  445. { for some subnodes }
  446. set_varstate(hloopvar,vs_written,[]);
  447. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  448. { ... now the instruction block }
  449. hblock:=statement;
  450. { variable is not used for loop counter anymore }
  451. if assigned(loopvarsym) then
  452. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  453. result:=cfornode.create(hloopvar,hfrom,hto,hblock,backward);
  454. { only in tp and mac pascal mode, we care about the value of the loop counter on loop exit
  455. I am not sure though, if this is the right rule, at least in delphi the loop counter is undefined
  456. on loop exit, we assume the same in all FPC modes }
  457. if ([m_objfpc,m_fpc,m_delphi]*current_settings.modeswitches)<>[] then
  458. Include(tfornode(Result).loopflags,lnf_dont_mind_loopvar_on_exit);
  459. end;
  460. function for_in_loop_create(hloopvar: tnode): tnode;
  461. var
  462. expr,hloopbody,hp: tnode;
  463. loopvarsym: tabstractvarsym;
  464. begin
  465. hp:=skip_nodes_before_load(hloopvar);
  466. if assigned(hp)and(hp.nodetype=loadn) then
  467. begin
  468. loopvarsym:=tabstractvarsym(tloadnode(hp).symtableentry);
  469. include(loopvarsym.varoptions,vo_is_loop_counter);
  470. end
  471. else
  472. loopvarsym:=nil;
  473. expr:=comp_expr([ef_accept_equal]);
  474. consume(_DO);
  475. set_varstate(hloopvar,vs_written,[]);
  476. set_varstate(hloopvar,vs_read,[vsf_must_be_valid]);
  477. hloopbody:=statement;
  478. if assigned(loopvarsym) then
  479. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  480. result:=create_for_in_loop(hloopvar,hloopbody,expr);
  481. expr.free;
  482. end;
  483. var
  484. hloopvar: tnode;
  485. begin
  486. { parse loop header }
  487. consume(_FOR);
  488. hloopvar:=factor(false,[]);
  489. valid_for_loopvar(hloopvar,true);
  490. if try_to_consume(_ASSIGNMENT) then
  491. result:=for_loop_create(hloopvar)
  492. else if try_to_consume(_IN) then
  493. result:=for_in_loop_create(hloopvar)
  494. else
  495. begin
  496. consume(_ASSIGNMENT); // fail
  497. result:=cerrornode.create;
  498. end;
  499. end;
  500. function _with_statement : tnode;
  501. var
  502. p : tnode;
  503. i : longint;
  504. st : TSymtable;
  505. newblock : tblocknode;
  506. newstatement : tstatementnode;
  507. calltempnode,
  508. tempnode : ttempcreatenode;
  509. valuenode,
  510. hp,
  511. refnode : tnode;
  512. hdef : tdef;
  513. helperdef : tobjectdef;
  514. hasimplicitderef : boolean;
  515. withsymtablelist : TFPObjectList;
  516. procedure pushobjchild(withdef,obj:tobjectdef);
  517. var
  518. parenthelperdef : tobjectdef;
  519. begin
  520. if not assigned(obj) then
  521. exit;
  522. pushobjchild(withdef,obj.childof);
  523. { we need to look for helpers that were defined for the parent
  524. class as well }
  525. search_last_objectpascal_helper(obj,current_structdef,parenthelperdef);
  526. { push the symtables of the helper's parents in reverse order }
  527. if assigned(parenthelperdef) then
  528. pushobjchild(withdef,parenthelperdef.childof);
  529. { keep the original tobjectdef as owner, because that is used for
  530. visibility of the symtable }
  531. st:=twithsymtable.create(withdef,obj.symtable.SymList,refnode.getcopy);
  532. symtablestack.push(st);
  533. withsymtablelist.add(st);
  534. { push the symtable of the helper }
  535. if assigned(parenthelperdef) then
  536. begin
  537. st:=twithsymtable.create(withdef,parenthelperdef.symtable.SymList,refnode.getcopy);
  538. symtablestack.push(st);
  539. withsymtablelist.add(st);
  540. end;
  541. end;
  542. begin
  543. calltempnode:=nil;
  544. p:=comp_expr([ef_accept_equal]);
  545. do_typecheckpass(p);
  546. if (p.nodetype=vecn) and
  547. (nf_memseg in p.flags) then
  548. CGMessage(parser_e_no_with_for_variable_in_other_segments);
  549. { "with procvar" can never mean anything, so always try
  550. to call it in case it returns a record/object/... }
  551. maybe_call_procvar(p,false);
  552. if (p.resultdef.typ in [objectdef,recorddef,classrefdef]) or
  553. ((p.resultdef.typ=undefineddef) and (df_generic in current_procinfo.procdef.defoptions)) then
  554. begin
  555. newblock:=nil;
  556. valuenode:=nil;
  557. tempnode:=nil;
  558. hp:=skip_nodes_before_load(p);
  559. if (hp.nodetype=loadn) and
  560. (
  561. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  562. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  563. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  564. ) and
  565. { MacPas objects are mapped to classes, and the MacPas compilers
  566. interpret with-statements with MacPas objects the same way
  567. as records (the object referenced by the with-statement
  568. must remain constant)
  569. }
  570. not(is_class(hp.resultdef) and
  571. (m_mac in current_settings.modeswitches)) then
  572. begin
  573. { simple load, we can reference direct }
  574. refnode:=p;
  575. end
  576. else
  577. begin
  578. { complex load, load in temp first }
  579. newblock:=internalstatements(newstatement);
  580. { when we can't take the address of p, load it in a temp }
  581. { since we may need its address later on }
  582. if not valid_for_addr(p,false) then
  583. begin
  584. calltempnode:=ctempcreatenode.create(p.resultdef,p.resultdef.size,tt_persistent,true);
  585. addstatement(newstatement,calltempnode);
  586. addstatement(newstatement,cassignmentnode.create(
  587. ctemprefnode.create(calltempnode),
  588. p));
  589. p:=ctemprefnode.create(calltempnode);
  590. typecheckpass(p);
  591. end;
  592. { several object types have implicit dereferencing }
  593. { is_implicit_pointer_object_type() returns true for records
  594. on the JVM target because they are implemented as classes
  595. there, but we definitely have to take their address here
  596. since otherwise a deep copy is made and changes are made to
  597. this copy rather than to the original one }
  598. hasimplicitderef:=
  599. (is_implicit_pointer_object_type(p.resultdef) or
  600. (p.resultdef.typ=classrefdef)) and
  601. not((target_info.system in systems_jvm) and
  602. ((p.resultdef.typ=recorddef) or
  603. is_object(p.resultdef)));
  604. if hasimplicitderef then
  605. hdef:=p.resultdef
  606. else
  607. hdef:=cpointerdef.create(p.resultdef);
  608. { load address of the value in a temp }
  609. tempnode:=ctempcreatenode.create_withnode(hdef,sizeof(pint),tt_persistent,true,p);
  610. typecheckpass(tnode(tempnode));
  611. valuenode:=p;
  612. refnode:=ctemprefnode.create(tempnode);
  613. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  614. { add address call for valuenode and deref for refnode if this
  615. is not done implicitly }
  616. if not hasimplicitderef then
  617. begin
  618. valuenode:=caddrnode.create_internal_nomark(valuenode);
  619. include(taddrnode(valuenode).addrnodeflags,anf_typedaddr);
  620. refnode:=cderefnode.create(refnode);
  621. fillchar(refnode.fileinfo,sizeof(tfileposinfo),0);
  622. end;
  623. addstatement(newstatement,tempnode);
  624. addstatement(newstatement,cassignmentnode.create(
  625. ctemprefnode.create(tempnode),
  626. valuenode));
  627. typecheckpass(refnode);
  628. end;
  629. { Note: the symtable of the helper is pushed after the following
  630. "case", the symtables of the helper's parents are passed in
  631. the "case" branches }
  632. withsymtablelist:=TFPObjectList.create(true);
  633. case p.resultdef.typ of
  634. objectdef :
  635. begin
  636. { do we have a helper for this type? }
  637. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  638. { push symtables of all parents in reverse order }
  639. pushobjchild(tobjectdef(p.resultdef),tobjectdef(p.resultdef).childof);
  640. { push symtables of all parents of the helper in reverse order }
  641. if assigned(helperdef) then
  642. pushobjchild(helperdef,helperdef.childof);
  643. { push object symtable }
  644. st:=twithsymtable.Create(tobjectdef(p.resultdef),tobjectdef(p.resultdef).symtable.SymList,refnode);
  645. symtablestack.push(st);
  646. withsymtablelist.add(st);
  647. end;
  648. classrefdef :
  649. begin
  650. { do we have a helper for this type? }
  651. search_last_objectpascal_helper(tobjectdef(tclassrefdef(p.resultdef).pointeddef),current_structdef,helperdef);
  652. { push symtables of all parents in reverse order }
  653. pushobjchild(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).childof);
  654. { push symtables of all parents of the helper in reverse order }
  655. if assigned(helperdef) then
  656. pushobjchild(helperdef,helperdef.childof);
  657. { push object symtable }
  658. st:=twithsymtable.Create(tobjectdef(tclassrefdef(p.resultdef).pointeddef),tobjectdef(tclassrefdef(p.resultdef).pointeddef).symtable.SymList,refnode);
  659. symtablestack.push(st);
  660. withsymtablelist.add(st);
  661. end;
  662. recorddef :
  663. begin
  664. { do we have a helper for this type? }
  665. search_last_objectpascal_helper(tabstractrecorddef(p.resultdef),current_structdef,helperdef);
  666. { push symtables of all parents of the helper in reverse order }
  667. if assigned(helperdef) then
  668. pushobjchild(helperdef,helperdef.childof);
  669. { push record symtable }
  670. st:=twithsymtable.create(trecorddef(p.resultdef),trecorddef(p.resultdef).symtable.SymList,refnode);
  671. symtablestack.push(st);
  672. withsymtablelist.add(st);
  673. end;
  674. undefineddef :
  675. begin
  676. if not(df_generic in current_procinfo.procdef.defoptions) then
  677. internalerror(2012122802);
  678. helperdef:=nil;
  679. { push record symtable }
  680. st:=twithsymtable.create(p.resultdef,nil,refnode);
  681. symtablestack.push(st);
  682. withsymtablelist.add(st);
  683. end;
  684. else
  685. internalerror(200601271);
  686. end;
  687. { push helper symtable }
  688. if assigned(helperdef) then
  689. begin
  690. st:=twithsymtable.Create(helperdef,helperdef.symtable.SymList,refnode.getcopy);
  691. symtablestack.push(st);
  692. withsymtablelist.add(st);
  693. end;
  694. if try_to_consume(_COMMA) then
  695. p:=_with_statement()
  696. else
  697. begin
  698. consume(_DO);
  699. if token<>_SEMICOLON then
  700. p:=statement
  701. else
  702. p:=cnothingnode.create;
  703. end;
  704. { remove symtables in reverse order from the stack }
  705. for i:=withsymtablelist.count-1 downto 0 do
  706. symtablestack.pop(TSymtable(withsymtablelist[i]));
  707. withsymtablelist.free;
  708. { Finalize complex withnode with destroy of temp }
  709. if assigned(newblock) then
  710. begin
  711. addstatement(newstatement,p);
  712. if assigned(tempnode) then
  713. addstatement(newstatement,ctempdeletenode.create(tempnode));
  714. if assigned(calltempnode) then
  715. addstatement(newstatement,ctempdeletenode.create(calltempnode));
  716. p:=newblock;
  717. end;
  718. result:=p;
  719. end
  720. else
  721. begin
  722. p.free;
  723. Message1(parser_e_false_with_expr,p.resultdef.GetTypeName);
  724. { try to recover from error }
  725. if try_to_consume(_COMMA) then
  726. begin
  727. hp:=_with_statement();
  728. if (hp=nil) then; { remove warning about unused }
  729. end
  730. else
  731. begin
  732. consume(_DO);
  733. { ignore all }
  734. if token<>_SEMICOLON then
  735. statement;
  736. end;
  737. result:=nil;
  738. end;
  739. end;
  740. function with_statement : tnode;
  741. begin
  742. consume(_WITH);
  743. with_statement:=_with_statement();
  744. end;
  745. function raise_statement : tnode;
  746. var
  747. p,pobj,paddr,pframe : tnode;
  748. begin
  749. pobj:=nil;
  750. paddr:=nil;
  751. pframe:=nil;
  752. consume(_RAISE);
  753. if not(token in endtokens) then
  754. begin
  755. { object }
  756. pobj:=comp_expr([ef_accept_equal]);
  757. if try_to_consume(_AT) then
  758. begin
  759. paddr:=comp_expr([ef_accept_equal]);
  760. if try_to_consume(_COMMA) then
  761. pframe:=comp_expr([ef_accept_equal]);
  762. end;
  763. end
  764. else
  765. begin
  766. if (block_type<>bt_except) then
  767. Message(parser_e_no_reraise_possible);
  768. end;
  769. if (po_noreturn in current_procinfo.procdef.procoptions) and (exceptblockcounter=0) then
  770. Message(parser_e_raise_with_noreturn_not_allowed);
  771. p:=craisenode.create(pobj,paddr,pframe);
  772. raise_statement:=p;
  773. end;
  774. function try_statement : tnode;
  775. procedure check_type_valid(var def: tdef);
  776. begin
  777. if not (is_class(def) or is_javaclass(def) or
  778. { skip showing error message the second time }
  779. (def.typ=errordef)) then
  780. begin
  781. Message1(type_e_class_type_expected,def.typename);
  782. def:=generrordef;
  783. end;
  784. end;
  785. var
  786. p_try_block,p_finally_block,first,last,
  787. p_default,p_specific,hp : tnode;
  788. ot : tDef;
  789. sym : tlocalvarsym;
  790. old_block_type : tblock_type;
  791. excepTSymtable : TSymtable;
  792. objname,objrealname : TIDString;
  793. srsym : tsym;
  794. srsymtable : TSymtable;
  795. t:ttoken;
  796. unit_found:boolean;
  797. oldcurrent_exceptblock: integer;
  798. filepostry : tfileposinfo;
  799. begin
  800. p_default:=nil;
  801. p_specific:=nil;
  802. excepTSymtable:=nil;
  803. last:=nil;
  804. { read statements to try }
  805. consume(_TRY);
  806. filepostry:=current_filepos;
  807. first:=nil;
  808. inc(exceptblockcounter);
  809. oldcurrent_exceptblock := current_exceptblock;
  810. current_exceptblock := exceptblockcounter;
  811. old_block_type := block_type;
  812. block_type := bt_body;
  813. while (token<>_FINALLY) and (token<>_EXCEPT) do
  814. begin
  815. if first=nil then
  816. begin
  817. last:=cstatementnode.create(statement,nil);
  818. first:=last;
  819. end
  820. else
  821. begin
  822. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  823. last:=tstatementnode(last).right;
  824. end;
  825. if not try_to_consume(_SEMICOLON) then
  826. break;
  827. consume_emptystats;
  828. end;
  829. p_try_block:=cblocknode.create(first);
  830. if try_to_consume(_FINALLY) then
  831. begin
  832. inc(exceptblockcounter);
  833. current_exceptblock := exceptblockcounter;
  834. p_finally_block:=statements_til_end;
  835. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  836. try_statement.fileinfo:=filepostry;
  837. end
  838. else
  839. begin
  840. consume(_EXCEPT);
  841. block_type:=bt_except;
  842. inc(exceptblockcounter);
  843. current_exceptblock := exceptblockcounter;
  844. ot:=generrordef;
  845. p_specific:=nil;
  846. if (idtoken=_ON) then
  847. { catch specific exceptions }
  848. begin
  849. repeat
  850. consume(_ON);
  851. if token=_ID then
  852. begin
  853. objname:=pattern;
  854. objrealname:=orgpattern;
  855. { can't use consume_sym here, because we need already
  856. to check for the colon }
  857. searchsym(objname,srsym,srsymtable);
  858. consume(_ID);
  859. { is a explicit name for the exception given ? }
  860. if try_to_consume(_COLON) then
  861. begin
  862. single_type(ot,[]);
  863. check_type_valid(ot);
  864. sym:=clocalvarsym.create(objrealname,vs_value,ot,[]);
  865. end
  866. else
  867. begin
  868. { check if type is valid, must be done here because
  869. with "e: Exception" the e is not necessary }
  870. { support unit.identifier }
  871. unit_found:=try_consume_unitsym_no_specialize(srsym,srsymtable,t,[],objname);
  872. if srsym=nil then
  873. begin
  874. identifier_not_found(orgpattern);
  875. srsym:=generrorsym;
  876. end;
  877. if unit_found then
  878. consume(t);
  879. { check if type is valid, must be done here because
  880. with "e: Exception" the e is not necessary }
  881. if (srsym.typ=typesym) then
  882. begin
  883. ot:=ttypesym(srsym).typedef;
  884. parse_nested_types(ot,false,false,nil);
  885. check_type_valid(ot);
  886. end
  887. else
  888. begin
  889. Message(type_e_type_id_expected);
  890. ot:=generrordef;
  891. end;
  892. { create dummy symbol so we don't need a special
  893. case in ncgflw, and so that we always know the
  894. type }
  895. sym:=clocalvarsym.create('$exceptsym',vs_value,ot,[]);
  896. end;
  897. excepTSymtable:=tstt_excepTSymtable.create;
  898. excepTSymtable.defowner:=current_procinfo.procdef;
  899. excepTSymtable.insert(sym);
  900. symtablestack.push(excepTSymtable);
  901. end
  902. else
  903. consume(_ID);
  904. consume(_DO);
  905. hp:=connode.create(nil,statement);
  906. if ot.typ=errordef then
  907. begin
  908. hp.free;
  909. hp:=cerrornode.create;
  910. end;
  911. if p_specific=nil then
  912. begin
  913. last:=hp;
  914. p_specific:=last;
  915. end
  916. else
  917. begin
  918. tonnode(last).left:=hp;
  919. last:=tonnode(last).left;
  920. end;
  921. { set the informations }
  922. { only if the creation of the onnode was succesful, it's possible }
  923. { that last and hp are errornodes (JM) }
  924. if last.nodetype = onn then
  925. begin
  926. tonnode(last).excepttype:=tobjectdef(ot);
  927. tonnode(last).excepTSymtable:=excepTSymtable;
  928. end;
  929. { remove exception symtable }
  930. if assigned(excepTSymtable) then
  931. begin
  932. symtablestack.pop(excepTSymtable);
  933. if last.nodetype <> onn then
  934. excepTSymtable.free;
  935. end;
  936. if not try_to_consume(_SEMICOLON) then
  937. break;
  938. consume_emptystats;
  939. until (token in [_END,_ELSE]);
  940. if try_to_consume(_ELSE) then
  941. begin
  942. { catch the other exceptions }
  943. p_default:=statements_til_end;
  944. end
  945. else
  946. consume(_END);
  947. end
  948. else
  949. begin
  950. { catch all exceptions }
  951. p_default:=statements_til_end;
  952. end;
  953. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  954. end;
  955. block_type:=old_block_type;
  956. current_exceptblock := oldcurrent_exceptblock;
  957. end;
  958. function _asm_statement : tnode;
  959. var
  960. asmstat : tasmnode;
  961. reg : tregister;
  962. asmreader : tbaseasmreader;
  963. entrypos : tfileposinfo;
  964. hl : TAsmList;
  965. begin
  966. Inside_asm_statement:=true;
  967. asmstat:=nil;
  968. hl:=nil;
  969. if assigned(asmmodeinfos[current_settings.asmmode]) then
  970. begin
  971. asmreader:=asmmodeinfos[current_settings.asmmode]^.casmreader.create;
  972. entrypos:=current_filepos;
  973. hl:=asmreader.assemble as TAsmList;
  974. if (not hl.empty) then
  975. begin
  976. { mark boundaries of assembler block, this is necessary for optimizer }
  977. hl.insert(tai_marker.create(mark_asmblockstart));
  978. hl.concat(tai_marker.create(mark_asmblockend));
  979. end;
  980. asmstat:=casmnode.create(hl);
  981. asmstat.fileinfo:=entrypos;
  982. asmreader.free;
  983. end
  984. else
  985. Message(parser_f_assembler_reader_not_supported);
  986. { Mark procedure that it has assembler blocks }
  987. include(current_procinfo.flags,pi_has_assembler_block);
  988. {$if defined(cpu8bitalu) or defined(cpu16bitalu)}
  989. { We assume the function result is always used in the TP mode }
  990. if (m_tp7 in current_settings.modeswitches) and
  991. not (po_assembler in current_procinfo.procdef.procoptions) and
  992. assigned(current_procinfo.procdef.funcretsym) then
  993. current_procinfo.procdef.funcretsym.IncRefCount;
  994. {$endif}
  995. { Read first the _ASM statement }
  996. consume(_ASM);
  997. { Force an empty register list for pure assembler routines,
  998. so that pass2 won't allocate volatile registers for them. }
  999. asmstat.has_registerlist:=(po_assembler in current_procinfo.procdef.procoptions);
  1000. { END is read, got a list of changed registers? }
  1001. if try_to_consume(_LECKKLAMMER) then
  1002. begin
  1003. if token<>_RECKKLAMMER then
  1004. begin
  1005. if po_assembler in current_procinfo.procdef.procoptions then
  1006. Message(parser_w_register_list_ignored);
  1007. repeat
  1008. { it's possible to specify the modified registers }
  1009. if token=_CSTRING then
  1010. reg:=std_regnum_search(lower(cstringpattern))
  1011. else if token=_CCHAR then
  1012. reg:=std_regnum_search(lower(pattern))
  1013. else
  1014. reg:=NR_NO;
  1015. if reg<>NR_NO then
  1016. begin
  1017. if not(po_assembler in current_procinfo.procdef.procoptions) and assigned(hl) then
  1018. begin
  1019. hl.Insert(tai_regalloc.alloc(reg,nil));
  1020. hl.Insert(tai_regalloc.markused(reg));
  1021. hl.Concat(tai_regalloc.dealloc(reg,nil));
  1022. end;
  1023. end
  1024. else
  1025. Message(asmr_e_invalid_register);
  1026. if token=_CCHAR then
  1027. consume(_CCHAR)
  1028. else
  1029. consume(_CSTRING);
  1030. if not try_to_consume(_COMMA) then
  1031. break;
  1032. until false;
  1033. asmstat.has_registerlist:=true;
  1034. end;
  1035. consume(_RECKKLAMMER);
  1036. end;
  1037. Inside_asm_statement:=false;
  1038. _asm_statement:=asmstat;
  1039. end;
  1040. { Old Turbo Pascal INLINE(data/data/...) }
  1041. function tp_inline_statement : tnode;
  1042. var
  1043. actype : taiconst_type;
  1044. function eval_intconst: asizeint;
  1045. var
  1046. cv : Tconstexprint;
  1047. def: tdef;
  1048. begin
  1049. cv:=get_intconst;
  1050. case actype of
  1051. aitconst_8bit:
  1052. def:=s8inttype;
  1053. aitconst_16bit:
  1054. def:=s16inttype;
  1055. else
  1056. def:=sizesinttype;
  1057. end;
  1058. if cv.uvalue>get_max_value(def).uvalue then
  1059. def:=get_unsigned_inttype(def);
  1060. adaptrange(def,cv,rc_implicit);
  1061. result:=cv.svalue;
  1062. end;
  1063. var
  1064. cur_line : longint;
  1065. w : asizeint;
  1066. hl : TAsmList;
  1067. asmstat : tasmnode;
  1068. sym : tsym;
  1069. symtable : TSymtable;
  1070. s : tsymstr;
  1071. ac : tai_const;
  1072. nesting : integer;
  1073. tokenbuf : tdynamicarray;
  1074. begin
  1075. consume(_INLINE);
  1076. consume(_LKLAMMER);
  1077. hl:=TAsmList.create;
  1078. asmstat:=casmnode.create(hl);
  1079. asmstat.fileinfo:=current_filepos;
  1080. tokenbuf:=tdynamicarray.Create(16);
  1081. cur_line:=0;
  1082. { Parse data blocks }
  1083. repeat
  1084. { Record one data block for further replaying.
  1085. This is needed since / is used as a data block delimiter and cause troubles
  1086. with constant evaluation which is allowed inside a data block. }
  1087. tokenbuf.reset;
  1088. current_scanner.startrecordtokens(tokenbuf);
  1089. nesting:=0;
  1090. while token<>_SLASH do
  1091. begin
  1092. case token of
  1093. _LKLAMMER:
  1094. inc(nesting);
  1095. _RKLAMMER:
  1096. begin
  1097. dec(nesting);
  1098. if nesting<0 then
  1099. break;
  1100. end;
  1101. _SEMICOLON:
  1102. consume(_RKLAMMER); { error }
  1103. else
  1104. ; {no action}
  1105. end;
  1106. consume(token);
  1107. end;
  1108. current_scanner.stoprecordtokens;
  1109. { Set the current token to ; to make the constant evaluator happy }
  1110. token:=_SEMICOLON;
  1111. { Parse recorded tokens }
  1112. current_scanner.startreplaytokens(tokenbuf,false);
  1113. if cur_line<>current_filepos.line then
  1114. begin
  1115. hl.concat(tai_force_line.Create);
  1116. cur_line:=current_filepos.line;
  1117. end;
  1118. { Data size override }
  1119. if try_to_consume(_GT) then
  1120. actype:=aitconst_16bit
  1121. else
  1122. if try_to_consume(_LT) then
  1123. actype:=aitconst_8bit
  1124. else
  1125. actype:=aitconst_128bit; { default size }
  1126. sym:=nil;
  1127. if token=_ID then
  1128. begin
  1129. if searchsym(pattern,sym,symtable) then
  1130. begin
  1131. if sym.typ in [staticvarsym,localvarsym,paravarsym] then
  1132. begin
  1133. { Address of the static symbol or base offset for local symbols }
  1134. consume(_ID);
  1135. if (sym.typ=staticvarsym) and not (actype in [aitconst_128bit,aitconst_ptr]) then
  1136. Message1(type_e_integer_expr_expected,sym.name);
  1137. { Additional offset }
  1138. if token in [_PLUS,_MINUS] then
  1139. w:=eval_intconst
  1140. else
  1141. w:=0;
  1142. if sym.typ=staticvarsym then
  1143. s:=sym.mangledname
  1144. else
  1145. s:=sym.name;
  1146. ac:=tai_const.Createname(s,w);
  1147. if actype=aitconst_128bit then
  1148. ac.consttype:=aitconst_ptr
  1149. else
  1150. ac.consttype:=actype;
  1151. { For a local symbol it is needed to generate a constant with the symbols's stack offset.
  1152. The stack offset is unavailable rigth now and will be resolved later in tcgasmnode.pass_generate_code.
  1153. Set sym.bind:=AB_NONE to indicate that this is a local symbol. }
  1154. if sym.typ<>staticvarsym then
  1155. ac.sym.bind:=AB_NONE;
  1156. hl.concat(ac);
  1157. end
  1158. else
  1159. if sym.typ=constsym then
  1160. sym:=nil
  1161. else
  1162. begin
  1163. consume(_ID);
  1164. Message(asmr_e_wrong_sym_type);
  1165. end;
  1166. end;
  1167. end;
  1168. if sym=nil then
  1169. begin
  1170. { Integer constant expression }
  1171. w:=eval_intconst;
  1172. case actype of
  1173. aitconst_8bit:
  1174. hl.concat(tai_const.Create_8bit(w));
  1175. aitconst_16bit:
  1176. hl.concat(tai_const.Create_16bit(w));
  1177. else
  1178. if w<$100 then
  1179. hl.concat(tai_const.Create_8bit(w))
  1180. else
  1181. hl.concat(tai_const.Create_sizeint(w));
  1182. end;
  1183. end;
  1184. if not try_to_consume(_SEMICOLON) then
  1185. consume(_RKLAMMER); {error}
  1186. until nesting<0;
  1187. tokenbuf.free;
  1188. { mark boundaries of assembler block, this is necessary for optimizer }
  1189. hl.insert(tai_marker.create(mark_asmblockstart));
  1190. hl.concat(tai_marker.create(mark_asmblockend));
  1191. { Mark procedure that it has assembler blocks }
  1192. include(current_procinfo.flags,pi_has_assembler_block);
  1193. { Assume the function result is always used }
  1194. if assigned(current_procinfo.procdef.funcretsym) then
  1195. current_procinfo.procdef.funcretsym.IncRefCount;
  1196. result:=asmstat;
  1197. end;
  1198. function statement : tnode;
  1199. var
  1200. p,
  1201. code : tnode;
  1202. filepos : tfileposinfo;
  1203. srsym : tsym;
  1204. srsymtable : TSymtable;
  1205. s : TIDString;
  1206. begin
  1207. filepos:=current_tokenpos;
  1208. code:=nil;
  1209. case token of
  1210. _GOTO :
  1211. begin
  1212. if not(cs_support_goto in current_settings.moduleswitches) then
  1213. Message(sym_e_goto_and_label_not_supported);
  1214. consume(_GOTO);
  1215. if (token<>_INTCONST) and (token<>_ID) then
  1216. begin
  1217. Message(sym_e_label_not_found);
  1218. code:=cerrornode.create;
  1219. end
  1220. else
  1221. begin
  1222. if token=_ID then
  1223. consume_sym(srsym,srsymtable)
  1224. else
  1225. begin
  1226. if token<>_INTCONST then
  1227. internalerror(201008021);
  1228. { strip leading 0's in iso mode }
  1229. if (([m_iso,m_extpas]*current_settings.modeswitches)<>[]) then
  1230. while (length(pattern)>1) and (pattern[1]='0') do
  1231. delete(pattern,1,1);
  1232. searchsym(pattern,srsym,srsymtable);
  1233. if srsym=nil then
  1234. begin
  1235. identifier_not_found(pattern);
  1236. srsym:=generrorsym;
  1237. srsymtable:=nil;
  1238. end;
  1239. consume(token);
  1240. end;
  1241. if srsym.typ<>labelsym then
  1242. begin
  1243. Message(sym_e_id_is_no_label_id);
  1244. code:=cerrornode.create;
  1245. end
  1246. else
  1247. begin
  1248. { goto outside the current scope? }
  1249. if srsym.owner<>current_procinfo.procdef.localst then
  1250. begin
  1251. { allowed? }
  1252. if not(m_non_local_goto in current_settings.modeswitches) then
  1253. Message(parser_e_goto_outside_proc);
  1254. include(current_procinfo.flags,pi_has_global_goto);
  1255. if is_nested_pd(current_procinfo.procdef) then
  1256. current_procinfo.set_needs_parentfp(srsym.owner.symtablelevel);
  1257. end;
  1258. code:=cgotonode.create(tlabelsym(srsym));
  1259. tgotonode(code).labelsym:=tlabelsym(srsym);
  1260. { set flag that this label is used }
  1261. tlabelsym(srsym).used:=true;
  1262. end;
  1263. end;
  1264. end;
  1265. _BEGIN :
  1266. code:=statement_block(_BEGIN);
  1267. _IF :
  1268. code:=if_statement;
  1269. _CASE :
  1270. code:=case_statement;
  1271. _REPEAT :
  1272. code:=repeat_statement;
  1273. _WHILE :
  1274. code:=while_statement;
  1275. _FOR :
  1276. code:=for_statement;
  1277. _WITH :
  1278. code:=with_statement;
  1279. _TRY :
  1280. code:=try_statement;
  1281. _RAISE :
  1282. code:=raise_statement;
  1283. { semicolons,else until and end are ignored }
  1284. _SEMICOLON,
  1285. _ELSE,
  1286. _UNTIL,
  1287. _END:
  1288. code:=cnothingnode.create;
  1289. _FAIL :
  1290. begin
  1291. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  1292. Message(parser_e_fail_only_in_constructor);
  1293. consume(_FAIL);
  1294. code:=cnodeutils.call_fail_node;
  1295. end;
  1296. _ASM :
  1297. begin
  1298. if parse_generic then
  1299. Message(parser_e_no_assembler_in_generic);
  1300. code:=_asm_statement;
  1301. end;
  1302. _PLUS:
  1303. begin
  1304. Message(parser_e_syntax_error);
  1305. consume(_PLUS);
  1306. end;
  1307. _INLINE:
  1308. begin
  1309. code:=tp_inline_statement;
  1310. end;
  1311. _EOF :
  1312. Message(scan_f_end_of_file);
  1313. else
  1314. begin
  1315. { don't typecheck yet, because that will also simplify, which may
  1316. result in not detecting certain kinds of syntax errors --
  1317. see mantis #15594 }
  1318. p:=expr(false);
  1319. { save the pattern here for latter usage, the label could be "000",
  1320. even if we read an expression, the pattern is still valid if it's really
  1321. a label (FK)
  1322. if you want to mess here, take care of
  1323. tests/webtbs/tw3546.pp
  1324. }
  1325. s:=pattern;
  1326. { When a colon follows a intconst then transform it into a label }
  1327. if (p.nodetype=ordconstn) and
  1328. try_to_consume(_COLON) then
  1329. begin
  1330. { in iso mode, 0003: is equal to 3: }
  1331. if (([m_iso,m_extpas]*current_settings.modeswitches)<>[]) then
  1332. searchsym(tostr(tordconstnode(p).value),srsym,srsymtable)
  1333. else
  1334. searchsym(s,srsym,srsymtable);
  1335. p.free;
  1336. if assigned(srsym) and
  1337. (srsym.typ=labelsym) then
  1338. begin
  1339. if tlabelsym(srsym).defined then
  1340. Message(sym_e_label_already_defined);
  1341. if symtablestack.top.symtablelevel<>srsymtable.symtablelevel then
  1342. begin
  1343. include(current_procinfo.flags,pi_has_interproclabel);
  1344. if (current_procinfo.procdef.proctypeoption in [potype_unitinit,potype_unitfinalize]) then
  1345. Message(sym_e_interprocgoto_into_init_final_code_not_allowed);
  1346. end;
  1347. tlabelsym(srsym).defined:=true;
  1348. p:=clabelnode.create(nil,tlabelsym(srsym));
  1349. tlabelsym(srsym).code:=p;
  1350. end
  1351. else
  1352. begin
  1353. Message1(sym_e_label_used_and_not_defined,s);
  1354. p:=cnothingnode.create;
  1355. end;
  1356. end;
  1357. if p.nodetype=labeln then
  1358. begin
  1359. { the pointer to the following instruction }
  1360. { isn't a very clean way }
  1361. if token in endtokens then
  1362. tlabelnode(p).left:=cnothingnode.create
  1363. else
  1364. tlabelnode(p).left:=statement();
  1365. { be sure to have left also typecheckpass }
  1366. typecheckpass(tlabelnode(p).left);
  1367. end
  1368. else
  1369. { change a load of a procvar to a call. this is also
  1370. supported in fpc mode }
  1371. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  1372. maybe_call_procvar(p,false);
  1373. { blockn support because a read/write is changed into a blocknode
  1374. with a separate statement for each read/write operation (JM)
  1375. the same is true for val() if the third parameter is not 32 bit
  1376. goto nodes are created by the compiler for non local exit statements, so
  1377. include them as well
  1378. }
  1379. if not(p.nodetype in [nothingn,errorn,calln,ifn,assignn,breakn,inlinen,
  1380. continuen,labeln,blockn,exitn,goton]) or
  1381. ((p.nodetype=inlinen) and
  1382. not is_void(p.resultdef)) or
  1383. ((p.nodetype=calln) and
  1384. (assigned(tcallnode(p).procdefinition)) and
  1385. (tcallnode(p).procdefinition.proctypeoption=potype_operator)) then
  1386. Message(parser_e_illegal_expression);
  1387. if not assigned(p.resultdef) then
  1388. do_typecheckpass(p);
  1389. { Specify that we don't use the value returned by the call.
  1390. This is used for :
  1391. - dispose of temp stack space
  1392. - dispose on FPU stack
  1393. - extended syntax checking }
  1394. if (p.nodetype=calln) then
  1395. begin
  1396. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  1397. { in $x- state, the function result must not be ignored }
  1398. if not(cs_extsyntax in current_settings.moduleswitches) and
  1399. not(is_void(p.resultdef)) and
  1400. { can be nil in case there was an error in the expression }
  1401. assigned(tcallnode(p).procdefinition) and
  1402. { allow constructor calls to drop the result if they are
  1403. called as instance methods instead of class methods }
  1404. not(
  1405. (tcallnode(p).procdefinition.proctypeoption=potype_constructor) and
  1406. is_class_or_object(tprocdef(tcallnode(p).procdefinition).struct) and
  1407. assigned(tcallnode(p).methodpointer) and
  1408. (tnode(tcallnode(p).methodpointer).resultdef.typ=objectdef)
  1409. ) then
  1410. Message(parser_e_illegal_expression);
  1411. end;
  1412. code:=p;
  1413. end;
  1414. end;
  1415. if assigned(code) then
  1416. begin
  1417. typecheckpass(code);
  1418. code.fileinfo:=filepos;
  1419. end;
  1420. statement:=code;
  1421. end;
  1422. function statement_block(starttoken : ttoken) : tnode;
  1423. var
  1424. first,last : tnode;
  1425. filepos : tfileposinfo;
  1426. begin
  1427. first:=nil;
  1428. last:=nil;
  1429. filepos:=current_tokenpos;
  1430. consume(starttoken);
  1431. while not((token=_END) or (token=_FINALIZATION)) do
  1432. begin
  1433. if first=nil then
  1434. begin
  1435. last:=cstatementnode.create(statement,nil);
  1436. first:=last;
  1437. end
  1438. else
  1439. begin
  1440. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  1441. last:=tstatementnode(last).right;
  1442. end;
  1443. if ((token=_END) or (token=_FINALIZATION)) then
  1444. break
  1445. else
  1446. begin
  1447. { if no semicolon, then error and go on }
  1448. if token<>_SEMICOLON then
  1449. begin
  1450. consume(_SEMICOLON);
  1451. consume_all_until(_SEMICOLON);
  1452. end;
  1453. consume(_SEMICOLON);
  1454. end;
  1455. consume_emptystats;
  1456. end;
  1457. { don't consume the finalization token, it is consumed when
  1458. reading the finalization block, but allow it only after
  1459. an initalization ! }
  1460. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1461. consume(_END);
  1462. last:=cblocknode.create(first);
  1463. last.fileinfo:=filepos;
  1464. statement_block:=last;
  1465. end;
  1466. function assembler_block : tnode;
  1467. var
  1468. p : tnode;
  1469. {$if not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1470. locals : longint;
  1471. {$endif not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1472. srsym : tsym;
  1473. begin
  1474. if parse_generic then
  1475. message(parser_e_no_assembler_in_generic);
  1476. { Rename the funcret so that recursive calls are possible }
  1477. if not is_void(current_procinfo.procdef.returndef) then
  1478. begin
  1479. srsym:=TSym(current_procinfo.procdef.localst.Find(current_procinfo.procdef.procsym.name));
  1480. if assigned(srsym) then
  1481. srsym.realname:='$hiddenresult';
  1482. end;
  1483. { delphi uses register calling for assembler methods }
  1484. if (m_delphi in current_settings.modeswitches) and
  1485. (po_assembler in current_procinfo.procdef.procoptions) and
  1486. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1487. current_procinfo.procdef.proccalloption:=pocall_register;
  1488. { force the asm statement }
  1489. if token<>_ASM then
  1490. consume(_ASM);
  1491. include(current_procinfo.flags,pi_is_assembler);
  1492. p:=_asm_statement;
  1493. {$if not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) and not(defined(mips))}
  1494. if (po_assembler in current_procinfo.procdef.procoptions) then
  1495. begin
  1496. { set the framepointer to esp for assembler functions when the
  1497. following conditions are met:
  1498. - if the are no local variables and parameters (except the allocated result)
  1499. - no reference to the result variable (refcount<=1)
  1500. - result is not stored as parameter
  1501. - target processor has optional frame pointer save
  1502. (vm, i386, vm only currently)
  1503. }
  1504. locals:=tabstractlocalsymtable(current_procinfo.procdef.parast).count_locals;
  1505. if (current_procinfo.procdef.localst.symtabletype=localsymtable) then
  1506. inc(locals,tabstractlocalsymtable(current_procinfo.procdef.localst).count_locals);
  1507. if (locals=0) and
  1508. not (current_procinfo.procdef.owner.symtabletype in [ObjectSymtable,recordsymtable]) and
  1509. (not assigned(current_procinfo.procdef.funcretsym) or
  1510. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs<=1)) and
  1511. not (df_generic in current_procinfo.procdef.defoptions) and
  1512. not(paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1513. begin
  1514. { Only need to set the framepointer, the locals will
  1515. be inserted with the correct reference in tcgasmnode.pass_generate_code }
  1516. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1517. end;
  1518. end;
  1519. {$endif not(defined(sparcgen)) and not(defined(arm)) and not(defined(avr)) not(defined(mipsel))}
  1520. { Flag the result as assigned when it is returned in a
  1521. register.
  1522. }
  1523. if assigned(current_procinfo.procdef.funcretsym) and
  1524. not (df_generic in current_procinfo.procdef.defoptions) and
  1525. (not paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) then
  1526. tabstractvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_initialised;
  1527. { because the END is already read we need to get the
  1528. last_endtoken_filepos here (PFV) }
  1529. last_endtoken_filepos:=current_tokenpos;
  1530. assembler_block:=p;
  1531. end;
  1532. end.