pstatmnt.pas 64 KB

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