pstatmnt.pas 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Does the parsing of the statements
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pstatmnt;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. tokens,node;
  23. function statement_block(starttoken : ttoken) : tnode;
  24. { reads an assembler block }
  25. function assembler_block : tnode;
  26. implementation
  27. uses
  28. { common }
  29. cutils,
  30. { global }
  31. globtype,globals,verbose,
  32. systems,
  33. { aasm }
  34. cpubase,aasmbase,aasmtai,
  35. { symtable }
  36. symconst,symbase,symtype,symdef,symsym,symtable,defutil,defcmp,
  37. paramgr,symutil,
  38. { pass 1 }
  39. pass_1,htypechk,
  40. nutils,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  41. { parser }
  42. scanner,
  43. pbase,pexpr,
  44. { codegen }
  45. procinfo,cgbase,
  46. { assembler reader }
  47. rabase
  48. ;
  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(true);
  56. consume(_THEN);
  57. if token<>_ELSE 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. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  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. while token<>_END do
  74. begin
  75. if first=nil then
  76. begin
  77. last:=cstatementnode.create(statement,nil);
  78. first:=last;
  79. end
  80. else
  81. begin
  82. last.right:=cstatementnode.create(statement,nil);
  83. last:=tstatementnode(last.right);
  84. end;
  85. if not try_to_consume(_SEMICOLON) then
  86. break;
  87. consume_emptystats;
  88. end;
  89. consume(_END);
  90. statements_til_end:=cblocknode.create(first);
  91. end;
  92. function case_statement : tnode;
  93. var
  94. { contains the label number of currently parsed case block }
  95. aktcaselabel : tasmlabel;
  96. firstlabel : boolean;
  97. root : pcaserecord;
  98. { the typ of the case expression }
  99. casedef : tdef;
  100. procedure newcaselabel(l,h : TConstExprInt;first:boolean);
  101. var
  102. hcaselabel : pcaserecord;
  103. procedure insertlabel(var p : pcaserecord);
  104. begin
  105. if p=nil then p:=hcaselabel
  106. else
  107. if (p^._low>hcaselabel^._low) and
  108. (p^._low>hcaselabel^._high) then
  109. if (hcaselabel^.statement = p^.statement) and
  110. (p^._low = hcaselabel^._high + 1) then
  111. begin
  112. p^._low := hcaselabel^._low;
  113. dispose(hcaselabel);
  114. end
  115. else
  116. insertlabel(p^.less)
  117. else
  118. if (p^._high<hcaselabel^._low) and
  119. (p^._high<hcaselabel^._high) then
  120. if (hcaselabel^.statement = p^.statement) and
  121. (p^._high+1 = hcaselabel^._low) then
  122. begin
  123. p^._high := hcaselabel^._high;
  124. dispose(hcaselabel);
  125. end
  126. else
  127. insertlabel(p^.greater)
  128. else Message(parser_e_double_caselabel);
  129. end;
  130. begin
  131. new(hcaselabel);
  132. hcaselabel^.less:=nil;
  133. hcaselabel^.greater:=nil;
  134. hcaselabel^.statement:=aktcaselabel;
  135. hcaselabel^.firstlabel:=first;
  136. objectlibrary.getlabel(hcaselabel^._at);
  137. hcaselabel^._low:=l;
  138. hcaselabel^._high:=h;
  139. insertlabel(root);
  140. end;
  141. var
  142. code,caseexpr,p,instruc,elseblock : tnode;
  143. hl1,hl2 : TConstExprInt;
  144. casedeferror : boolean;
  145. begin
  146. consume(_CASE);
  147. caseexpr:=comp_expr(true);
  148. { determines result type }
  149. do_resulttypepass(caseexpr);
  150. set_varstate(caseexpr,vs_used,true);
  151. casedeferror:=false;
  152. casedef:=caseexpr.resulttype.def;
  153. if (not assigned(casedef)) or
  154. not(is_ordinal(casedef)) then
  155. begin
  156. CGMessage(type_e_ordinal_expr_expected);
  157. { create a correct tree }
  158. caseexpr.free;
  159. caseexpr:=cordconstnode.create(0,u32inttype,false);
  160. { set error flag so no rangechecks are done }
  161. casedeferror:=true;
  162. end;
  163. consume(_OF);
  164. root:=nil;
  165. instruc:=nil;
  166. repeat
  167. objectlibrary.getlabel(aktcaselabel);
  168. firstlabel:=true;
  169. { maybe an instruction has more case labels }
  170. repeat
  171. p:=expr;
  172. if is_widechar(casedef) then
  173. begin
  174. if (p.nodetype=rangen) then
  175. begin
  176. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  177. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  178. do_resulttypepass(trangenode(p).left);
  179. do_resulttypepass(trangenode(p).right);
  180. end
  181. else
  182. begin
  183. p:=ctypeconvnode.create(p,cwidechartype);
  184. do_resulttypepass(p);
  185. end;
  186. end;
  187. hl1:=0;
  188. hl2:=0;
  189. if (p.nodetype=rangen) then
  190. begin
  191. { type checking for case statements }
  192. if is_subequal(casedef, trangenode(p).left.resulttype.def) and
  193. is_subequal(casedef, trangenode(p).right.resulttype.def) then
  194. begin
  195. hl1:=get_ordinal_value(trangenode(p).left);
  196. hl2:=get_ordinal_value(trangenode(p).right);
  197. if hl1>hl2 then
  198. CGMessage(parser_e_case_lower_less_than_upper_bound);
  199. if not casedeferror then
  200. begin
  201. testrange(casedef,hl1,false);
  202. testrange(casedef,hl2,false);
  203. end;
  204. end
  205. else
  206. CGMessage(parser_e_case_mismatch);
  207. newcaselabel(hl1,hl2,firstlabel);
  208. end
  209. else
  210. begin
  211. { type checking for case statements }
  212. if not is_subequal(casedef, p.resulttype.def) then
  213. CGMessage(parser_e_case_mismatch);
  214. hl1:=get_ordinal_value(p);
  215. if not casedeferror then
  216. testrange(casedef,hl1,false);
  217. newcaselabel(hl1,hl1,firstlabel);
  218. end;
  219. p.free;
  220. if token=_COMMA then
  221. consume(_COMMA)
  222. else
  223. break;
  224. firstlabel:=false;
  225. until false;
  226. consume(_COLON);
  227. { handles instruction block }
  228. p:=clabelnode.createcase(aktcaselabel,statement);
  229. { concats instruction }
  230. instruc:=cstatementnode.create(p,instruc);
  231. if not(token in [_ELSE,_OTHERWISE,_END]) then
  232. consume(_SEMICOLON);
  233. until (token in [_ELSE,_OTHERWISE,_END]);
  234. if (token in [_ELSE,_OTHERWISE]) then
  235. begin
  236. if not try_to_consume(_ELSE) then
  237. consume(_OTHERWISE);
  238. elseblock:=statements_til_end;
  239. end
  240. else
  241. begin
  242. elseblock:=nil;
  243. consume(_END);
  244. end;
  245. code:=ccasenode.create(caseexpr,instruc,root);
  246. tcasenode(code).elseblock:=elseblock;
  247. case_statement:=code;
  248. end;
  249. function repeat_statement : tnode;
  250. var
  251. first,last,p_e : tnode;
  252. begin
  253. consume(_REPEAT);
  254. first:=nil;
  255. while token<>_UNTIL do
  256. begin
  257. if first=nil then
  258. begin
  259. last:=cstatementnode.create(statement,nil);
  260. first:=last;
  261. end
  262. else
  263. begin
  264. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  265. last:=tstatementnode(last).right;
  266. end;
  267. if not try_to_consume(_SEMICOLON) then
  268. break;
  269. consume_emptystats;
  270. end;
  271. consume(_UNTIL);
  272. first:=cblocknode.create(first);
  273. p_e:=comp_expr(true);
  274. repeat_statement:=genloopnode(whilerepeatn,p_e,first,nil,true);
  275. end;
  276. function while_statement : tnode;
  277. var
  278. p_e,p_a : tnode;
  279. begin
  280. consume(_WHILE);
  281. p_e:=comp_expr(true);
  282. consume(_DO);
  283. p_a:=statement;
  284. while_statement:=genloopnode(whilerepeatn,p_e,p_a,nil,false);
  285. end;
  286. function for_statement : tnode;
  287. var
  288. p_e,tovalue,p_a : tnode;
  289. backward : boolean;
  290. loopvarsym : tvarsym;
  291. hp : tnode;
  292. begin
  293. { parse loop header }
  294. consume(_FOR);
  295. p_e:=expr;
  296. { Check loop variable }
  297. hp:=nil;
  298. loopvarsym:=nil;
  299. if (p_e.nodetype=assignn) then
  300. begin
  301. hp:=tassignmentnode(p_e).left;
  302. { variable must be an ordinal, int64 is not allowed for 32bit targets }
  303. if not(is_ordinal(hp.resulttype.def))
  304. {$ifndef cpu64bit}
  305. or is_64bitint(hp.resulttype.def)
  306. {$endif cpu64bit}
  307. then
  308. MessagePos(hp.fileinfo,type_e_ordinal_expr_expected);
  309. { record fields are also allowed in tp7 }
  310. while assigned(hp) and
  311. (
  312. (hp.nodetype=subscriptn) or
  313. ((hp.nodetype=vecn) and
  314. is_constintnode(tvecnode(hp).right)) or
  315. ((hp.nodetype=typeconvn) and
  316. (ttypeconvnode(hp).convtype=tc_equal))
  317. ) do
  318. hp:=tunarynode(hp).left;
  319. end;
  320. if assigned(hp) and
  321. (hp.nodetype=loadn) then
  322. begin
  323. case tloadnode(hp).symtableentry.typ of
  324. varsym :
  325. begin
  326. { we need a simple loadn and the load must be in a global symtable or
  327. in the same level as the para of the current proc }
  328. if (
  329. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  330. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  331. ) and
  332. not(
  333. (tloadnode(hp).symtableentry.typ=varsym) and
  334. ((tvarsym(tloadnode(hp).symtableentry).varspez in [vs_var,vs_out]) or
  335. (vo_is_thread_var in tvarsym(tloadnode(hp).symtableentry).varoptions))
  336. ) then
  337. begin
  338. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_used;
  339. { Assigning for-loop variable is only allowed in tp7 }
  340. if not(m_tp7 in aktmodeswitches) then
  341. begin
  342. loopvarsym:=tvarsym(tloadnode(hp).symtableentry);
  343. include(loopvarsym.varoptions,vo_is_loop_counter);
  344. end;
  345. end
  346. else
  347. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  348. end;
  349. typedconstsym :
  350. begin
  351. { Bad programming, only allowed in tp7 mode }
  352. if not(m_tp7 in aktmodeswitches) then
  353. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  354. end;
  355. else
  356. MessagePos(hp.fileinfo,type_e_illegal_count_var);
  357. end;
  358. end
  359. else
  360. Message(parser_e_illegal_expression);
  361. if token=_DOWNTO then
  362. begin
  363. consume(_DOWNTO);
  364. backward:=true;
  365. end
  366. else
  367. begin
  368. consume(_TO);
  369. backward:=false;
  370. end;
  371. tovalue:=comp_expr(true);
  372. consume(_DO);
  373. { ... now the instruction block }
  374. p_a:=statement;
  375. { variable is not used a loop counter anymore }
  376. if assigned(loopvarsym) then
  377. exclude(loopvarsym.varoptions,vo_is_loop_counter);
  378. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  379. end;
  380. function _with_statement : tnode;
  381. var
  382. right,p : tnode;
  383. i,levelcount : longint;
  384. withsymtable,symtab : tsymtable;
  385. obj : tobjectdef;
  386. hp : tnode;
  387. newblock : tblocknode;
  388. newstatement : tstatementnode;
  389. calltempp,
  390. loadp : ttempcreatenode;
  391. refp : tnode;
  392. htype : ttype;
  393. hasimplicitderef : boolean;
  394. begin
  395. p:=comp_expr(true);
  396. do_resulttypepass(p);
  397. set_varstate(p,vs_used,false);
  398. right:=nil;
  399. if (not codegenerror) and
  400. (p.resulttype.def.deftype in [objectdef,recorddef]) then
  401. begin
  402. newblock:=nil;
  403. { ignore nodes that don't add instructions in the tree }
  404. hp:=p;
  405. while { equal type conversions }
  406. (
  407. (hp.nodetype=typeconvn) and
  408. (ttypeconvnode(hp).convtype=tc_equal)
  409. ) or
  410. { constant array index }
  411. (
  412. (hp.nodetype=vecn) and
  413. (tvecnode(hp).right.nodetype=ordconstn)
  414. ) do
  415. hp:=tunarynode(hp).left;
  416. if (hp.nodetype=loadn) and
  417. (
  418. (tloadnode(hp).symtable=current_procinfo.procdef.localst) or
  419. (tloadnode(hp).symtable=current_procinfo.procdef.parast) or
  420. (tloadnode(hp).symtable.symtabletype in [staticsymtable,globalsymtable])
  421. ) then
  422. begin
  423. { simple load, we can reference direct }
  424. loadp:=nil;
  425. refp:=p;
  426. end
  427. else
  428. begin
  429. calltempp:=nil;
  430. { complex load, load in temp first }
  431. newblock:=internalstatements(newstatement);
  432. { when right is a call then load it first in a temp }
  433. if p.nodetype=calln then
  434. begin
  435. calltempp:=ctempcreatenode.create(p.resulttype,p.resulttype.def.size,tt_persistent);
  436. addstatement(newstatement,calltempp);
  437. addstatement(newstatement,cassignmentnode.create(
  438. ctemprefnode.create(calltempp),
  439. p));
  440. p:=ctemprefnode.create(calltempp);
  441. resulttypepass(p);
  442. end;
  443. { classes and interfaces have implicit dereferencing }
  444. hasimplicitderef:=is_class_or_interface(p.resulttype.def);
  445. if hasimplicitderef then
  446. htype:=p.resulttype
  447. else
  448. htype.setdef(tpointerdef.create(p.resulttype));
  449. {$ifdef WITHNODEDEBUG}
  450. { we can't generate debuginfo for a withnode stored in a }
  451. { register }
  452. if (cs_debuginfo in aktmoduleswitches) then
  453. loadp:=ctempcreatenode.create(htype,sizeof(aint),tt_persistent)
  454. else
  455. {$endif WITHNODEDEBUG}
  456. loadp:=ctempcreatenode.create_reg(htype,sizeof(aint),tt_persistent);
  457. resulttypepass(loadp);
  458. if hasimplicitderef then
  459. begin
  460. hp:=p;
  461. refp:=ctemprefnode.create(loadp);
  462. end
  463. else
  464. begin
  465. hp:=caddrnode.create(p);
  466. refp:=cderefnode.create(ctemprefnode.create(loadp));
  467. end;
  468. addstatement(newstatement,loadp);
  469. addstatement(newstatement,cassignmentnode.create(
  470. ctemprefnode.create(loadp),
  471. hp));
  472. resulttypepass(refp);
  473. end;
  474. case p.resulttype.def.deftype of
  475. objectdef :
  476. begin
  477. obj:=tobjectdef(p.resulttype.def);
  478. withsymtable:=twithsymtable.Create(obj,obj.symtable.symsearch,refp);
  479. { include also all parent symtables }
  480. levelcount:=1;
  481. obj:=obj.childof;
  482. symtab:=withsymtable;
  483. while assigned(obj) do
  484. begin
  485. { keep the original tobjectdef as owner, because that is used for
  486. visibility of the symtable }
  487. symtab.next:=twithsymtable.create(tobjectdef(p.resulttype.def),obj.symtable.symsearch,refp.getcopy);
  488. symtab:=symtab.next;
  489. obj:=obj.childof;
  490. inc(levelcount);
  491. end;
  492. symtab.next:=symtablestack;
  493. symtablestack:=withsymtable;
  494. end;
  495. recorddef :
  496. begin
  497. symtab:=trecorddef(p.resulttype.def).symtable;
  498. levelcount:=1;
  499. withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch,refp);
  500. withsymtable.next:=symtablestack;
  501. symtablestack:=withsymtable;
  502. end;
  503. end;
  504. if try_to_consume(_COMMA) then
  505. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif}
  506. else
  507. begin
  508. consume(_DO);
  509. if token<>_SEMICOLON then
  510. right:=statement
  511. else
  512. right:=cerrornode.create;
  513. end;
  514. { remove symtables from the stack }
  515. for i:=1 to levelcount do
  516. symtablestack:=symtablestack.next;
  517. p:=cwithnode.create(right,twithsymtable(withsymtable),levelcount,refp);
  518. { Finalize complex withnode with destroy of temp }
  519. if assigned(newblock) then
  520. begin
  521. addstatement(newstatement,p);
  522. addstatement(newstatement,ctempdeletenode.create(loadp));
  523. if assigned(calltempp) then
  524. addstatement(newstatement,ctempdeletenode.create(calltempp));
  525. p:=newblock;
  526. end;
  527. _with_statement:=p;
  528. end
  529. else
  530. begin
  531. p.free;
  532. Message(parser_e_false_with_expr);
  533. { try to recover from error }
  534. if try_to_consume(_COMMA) then
  535. begin
  536. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  537. if (hp=nil) then; { remove warning about unused }
  538. end
  539. else
  540. begin
  541. consume(_DO);
  542. { ignore all }
  543. if token<>_SEMICOLON then
  544. statement;
  545. end;
  546. _with_statement:=nil;
  547. end;
  548. end;
  549. function with_statement : tnode;
  550. begin
  551. consume(_WITH);
  552. with_statement:=_with_statement;
  553. end;
  554. function raise_statement : tnode;
  555. var
  556. p,pobj,paddr,pframe : tnode;
  557. begin
  558. pobj:=nil;
  559. paddr:=nil;
  560. pframe:=nil;
  561. consume(_RAISE);
  562. if not(token in endtokens) then
  563. begin
  564. { object }
  565. pobj:=comp_expr(true);
  566. if try_to_consume(_AT) then
  567. begin
  568. paddr:=comp_expr(true);
  569. if try_to_consume(_COMMA) then
  570. pframe:=comp_expr(true);
  571. end;
  572. end
  573. else
  574. begin
  575. if (block_type<>bt_except) then
  576. Message(parser_e_no_reraise_possible);
  577. end;
  578. p:=craisenode.create(pobj,paddr,pframe);
  579. raise_statement:=p;
  580. end;
  581. function try_statement : tnode;
  582. var
  583. p_try_block,p_finally_block,first,last,
  584. p_default,p_specific,hp : tnode;
  585. ot : ttype;
  586. sym : tvarsym;
  587. old_block_type : tblock_type;
  588. exceptsymtable : tsymtable;
  589. objname,objrealname : stringid;
  590. srsym : tsym;
  591. srsymtable : tsymtable;
  592. oldaktexceptblock: integer;
  593. begin
  594. include(current_procinfo.flags,pi_uses_exceptions);
  595. p_default:=nil;
  596. p_specific:=nil;
  597. { read statements to try }
  598. consume(_TRY);
  599. first:=nil;
  600. inc(exceptblockcounter);
  601. oldaktexceptblock := aktexceptblock;
  602. aktexceptblock := exceptblockcounter;
  603. while (token<>_FINALLY) and (token<>_EXCEPT) do
  604. begin
  605. if first=nil then
  606. begin
  607. last:=cstatementnode.create(statement,nil);
  608. first:=last;
  609. end
  610. else
  611. begin
  612. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  613. last:=tstatementnode(last).right;
  614. end;
  615. if not try_to_consume(_SEMICOLON) then
  616. break;
  617. consume_emptystats;
  618. end;
  619. p_try_block:=cblocknode.create(first);
  620. if try_to_consume(_FINALLY) then
  621. begin
  622. inc(exceptblockcounter);
  623. aktexceptblock := exceptblockcounter;
  624. p_finally_block:=statements_til_end;
  625. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  626. end
  627. else
  628. begin
  629. consume(_EXCEPT);
  630. old_block_type:=block_type;
  631. block_type:=bt_except;
  632. inc(exceptblockcounter);
  633. aktexceptblock := exceptblockcounter;
  634. ot:=generrortype;
  635. p_specific:=nil;
  636. if (idtoken=_ON) then
  637. { catch specific exceptions }
  638. begin
  639. repeat
  640. consume(_ID);
  641. if token=_ID then
  642. begin
  643. objname:=pattern;
  644. objrealname:=orgpattern;
  645. { can't use consume_sym here, because we need already
  646. to check for the colon }
  647. searchsym(objname,srsym,srsymtable);
  648. consume(_ID);
  649. { is a explicit name for the exception given ? }
  650. if try_to_consume(_COLON) then
  651. begin
  652. consume_sym(srsym,srsymtable);
  653. if (srsym.typ=typesym) and
  654. is_class(ttypesym(srsym).restype.def) then
  655. begin
  656. ot:=ttypesym(srsym).restype;
  657. sym:=tvarsym.create(objrealname,vs_value,ot);
  658. end
  659. else
  660. begin
  661. sym:=tvarsym.create(objrealname,vs_value,generrortype);
  662. if (srsym.typ=typesym) then
  663. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  664. else
  665. Message1(type_e_class_type_expected,ot.def.typename);
  666. end;
  667. exceptsymtable:=tstt_exceptsymtable.create;
  668. exceptsymtable.insert(sym);
  669. { insert the exception symtable stack }
  670. exceptsymtable.next:=symtablestack;
  671. symtablestack:=exceptsymtable;
  672. end
  673. else
  674. begin
  675. { check if type is valid, must be done here because
  676. with "e: Exception" the e is not necessary }
  677. if srsym=nil then
  678. begin
  679. identifier_not_found(objrealname);
  680. srsym:=generrorsym;
  681. end;
  682. { support unit.identifier }
  683. if srsym.typ=unitsym then
  684. begin
  685. consume(_POINT);
  686. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  687. if srsym=nil then
  688. begin
  689. identifier_not_found(orgpattern);
  690. srsym:=generrorsym;
  691. end;
  692. consume(_ID);
  693. end;
  694. { check if type is valid, must be done here because
  695. with "e: Exception" the e is not necessary }
  696. if (srsym.typ=typesym) and
  697. is_class(ttypesym(srsym).restype.def) then
  698. ot:=ttypesym(srsym).restype
  699. else
  700. begin
  701. ot:=generrortype;
  702. if (srsym.typ=typesym) then
  703. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  704. else
  705. Message1(type_e_class_type_expected,ot.def.typename);
  706. end;
  707. exceptsymtable:=nil;
  708. end;
  709. end
  710. else
  711. consume(_ID);
  712. consume(_DO);
  713. hp:=connode.create(nil,statement);
  714. if ot.def.deftype=errordef then
  715. begin
  716. hp.free;
  717. hp:=cerrornode.create;
  718. end;
  719. if p_specific=nil then
  720. begin
  721. last:=hp;
  722. p_specific:=last;
  723. end
  724. else
  725. begin
  726. tonnode(last).left:=hp;
  727. last:=tonnode(last).left;
  728. end;
  729. { set the informations }
  730. { only if the creation of the onnode was succesful, it's possible }
  731. { that last and hp are errornodes (JM) }
  732. if last.nodetype = onn then
  733. begin
  734. tonnode(last).excepttype:=tobjectdef(ot.def);
  735. tonnode(last).exceptsymtable:=exceptsymtable;
  736. end;
  737. { remove exception symtable }
  738. if assigned(exceptsymtable) then
  739. begin
  740. symtablestack:=symtablestack.next;
  741. if last.nodetype <> onn then
  742. exceptsymtable.free;
  743. end;
  744. if not try_to_consume(_SEMICOLON) then
  745. break;
  746. consume_emptystats;
  747. until (token in [_END,_ELSE]);
  748. if try_to_consume(_ELSE) then
  749. begin
  750. { catch the other exceptions }
  751. p_default:=statements_til_end;
  752. end
  753. else
  754. consume(_END);
  755. end
  756. else
  757. begin
  758. { catch all exceptions }
  759. p_default:=statements_til_end;
  760. end;
  761. block_type:=old_block_type;
  762. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  763. end;
  764. aktexceptblock := oldaktexceptblock;
  765. end;
  766. function _asm_statement : tnode;
  767. var
  768. asmstat : tasmnode;
  769. Marker : tai;
  770. reg : tregister;
  771. asmreader : tbaseasmreader;
  772. begin
  773. Inside_asm_statement:=true;
  774. if assigned(asmmodeinfos[aktasmmode]) then
  775. begin
  776. asmreader:=asmmodeinfos[aktasmmode]^.casmreader.create;
  777. asmstat:=casmnode.create(asmreader.assemble as taasmoutput);
  778. asmreader.free;
  779. end
  780. else
  781. Message(parser_f_assembler_reader_not_supported);
  782. { Read first the _ASM statement }
  783. consume(_ASM);
  784. { END is read, got a list of changed registers? }
  785. if try_to_consume(_LECKKLAMMER) then
  786. begin
  787. asmstat.used_regs_fpu:=[0..first_fpu_imreg-1];
  788. if token<>_RECKKLAMMER then
  789. begin
  790. repeat
  791. { it's possible to specify the modified registers }
  792. reg:=std_regnum_search(lower(pattern));
  793. if reg<>NR_NO then
  794. begin
  795. if getregtype(reg)=R_INTREGISTER then
  796. include(asmstat.used_regs_int,getsupreg(reg));
  797. end
  798. else
  799. Message(asmr_e_invalid_register);
  800. consume(_CSTRING);
  801. if not try_to_consume(_COMMA) then
  802. break;
  803. until false;
  804. end;
  805. consume(_RECKKLAMMER);
  806. end
  807. else
  808. begin
  809. asmstat.used_regs_int:=paramanager.get_volatile_registers_int(current_procinfo.procdef.proccalloption);
  810. asmstat.used_regs_fpu:=paramanager.get_volatile_registers_fpu(current_procinfo.procdef.proccalloption);
  811. end;
  812. { mark the start and the end of the assembler block
  813. this is needed for the optimizer }
  814. If Assigned(AsmStat.p_asm) Then
  815. Begin
  816. Marker := Tai_Marker.Create(AsmBlockStart);
  817. AsmStat.p_asm.Insert(Marker);
  818. Marker := Tai_Marker.Create(AsmBlockEnd);
  819. AsmStat.p_asm.Concat(Marker);
  820. End;
  821. Inside_asm_statement:=false;
  822. _asm_statement:=asmstat;
  823. end;
  824. function statement : tnode;
  825. var
  826. p : tnode;
  827. code : tnode;
  828. filepos : tfileposinfo;
  829. srsym : tsym;
  830. srsymtable : tsymtable;
  831. s : stringid;
  832. begin
  833. filepos:=akttokenpos;
  834. case token of
  835. _GOTO :
  836. begin
  837. if not(cs_support_goto in aktmoduleswitches)then
  838. Message(sym_e_goto_and_label_not_supported);
  839. consume(_GOTO);
  840. if (token<>_INTCONST) and (token<>_ID) then
  841. begin
  842. Message(sym_e_label_not_found);
  843. code:=cerrornode.create;
  844. end
  845. else
  846. begin
  847. if token=_ID then
  848. consume_sym(srsym,srsymtable)
  849. else
  850. begin
  851. searchsym(pattern,srsym,srsymtable);
  852. if srsym=nil then
  853. begin
  854. identifier_not_found(pattern);
  855. srsym:=generrorsym;
  856. srsymtable:=nil;
  857. end;
  858. consume(token);
  859. end;
  860. if srsym.typ<>labelsym then
  861. begin
  862. Message(sym_e_id_is_no_label_id);
  863. code:=cerrornode.create;
  864. end
  865. else
  866. begin
  867. { goto is only allowed to labels within the current scope }
  868. if srsym.owner<>current_procinfo.procdef.localst then
  869. CGMessage(parser_e_goto_outside_proc);
  870. code:=cgotonode.create(tlabelsym(srsym));
  871. tgotonode(code).labsym:=tlabelsym(srsym);
  872. { set flag that this label is used }
  873. tlabelsym(srsym).used:=true;
  874. end;
  875. end;
  876. end;
  877. _BEGIN :
  878. code:=statement_block(_BEGIN);
  879. _IF :
  880. code:=if_statement;
  881. _CASE :
  882. code:=case_statement;
  883. _REPEAT :
  884. code:=repeat_statement;
  885. _WHILE :
  886. code:=while_statement;
  887. _FOR :
  888. code:=for_statement;
  889. _WITH :
  890. code:=with_statement;
  891. _TRY :
  892. code:=try_statement;
  893. _RAISE :
  894. code:=raise_statement;
  895. { semicolons,else until and end are ignored }
  896. _SEMICOLON,
  897. _ELSE,
  898. _UNTIL,
  899. _END:
  900. code:=cnothingnode.create;
  901. _FAIL :
  902. begin
  903. if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
  904. Message(parser_e_fail_only_in_constructor);
  905. consume(_FAIL);
  906. code:=call_fail_node;
  907. end;
  908. _ASM :
  909. code:=_asm_statement;
  910. _EOF :
  911. Message(scan_f_end_of_file);
  912. else
  913. begin
  914. p:=expr;
  915. { When a colon follows a intconst then transform it into a label }
  916. if (p.nodetype=ordconstn) and
  917. try_to_consume(_COLON) then
  918. begin
  919. s:=tostr(tordconstnode(p).value);
  920. p.free;
  921. searchsym(s,srsym,srsymtable);
  922. if assigned(srsym) and
  923. (srsym.typ=labelsym) then
  924. begin
  925. if tlabelsym(srsym).defined then
  926. Message(sym_e_label_already_defined);
  927. tlabelsym(srsym).defined:=true;
  928. p:=clabelnode.create(tlabelsym(srsym),nil);
  929. end
  930. else
  931. begin
  932. Message1(sym_e_label_used_and_not_defined,s);
  933. p:=cnothingnode.create;
  934. end;
  935. end;
  936. if p.nodetype=labeln then
  937. begin
  938. { the pointer to the following instruction }
  939. { isn't a very clean way }
  940. if token in endtokens then
  941. tlabelnode(p).left:=cnothingnode.create
  942. else
  943. tlabelnode(p).left:=statement{$ifdef FPCPROCVAR}(){$endif};
  944. { be sure to have left also resulttypepass }
  945. resulttypepass(tlabelnode(p).left);
  946. end
  947. else
  948. { change a load of a procvar to a call. this is also
  949. supported in fpc mode }
  950. if p.nodetype in [vecn,derefn,typeconvn,subscriptn,loadn] then
  951. maybe_call_procvar(p,false);
  952. { blockn support because a read/write is changed into a blocknode }
  953. { with a separate statement for each read/write operation (JM) }
  954. { the same is true for val() if the third parameter is not 32 bit }
  955. if not(p.nodetype in [nothingn,calln,ifn,assignn,breakn,inlinen,
  956. continuen,labeln,blockn,exitn]) then
  957. Message(parser_e_illegal_expression);
  958. { Specify that we don't use the value returned by the call.
  959. This is used for :
  960. - dispose of temp stack space
  961. - dispose on FPU stack }
  962. if (p.nodetype=calln) then
  963. exclude(tcallnode(p).callnodeflags,cnf_return_value_used);
  964. code:=p;
  965. end;
  966. end;
  967. if assigned(code) then
  968. code.set_tree_filepos(filepos);
  969. statement:=code;
  970. end;
  971. function statement_block(starttoken : ttoken) : tnode;
  972. var
  973. first,last : tnode;
  974. filepos : tfileposinfo;
  975. begin
  976. first:=nil;
  977. filepos:=akttokenpos;
  978. consume(starttoken);
  979. while not(token in [_END,_FINALIZATION]) do
  980. begin
  981. if first=nil then
  982. begin
  983. last:=cstatementnode.create(statement,nil);
  984. first:=last;
  985. end
  986. else
  987. begin
  988. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  989. last:=tstatementnode(last).right;
  990. end;
  991. if (token in [_END,_FINALIZATION]) then
  992. break
  993. else
  994. begin
  995. { if no semicolon, then error and go on }
  996. if token<>_SEMICOLON then
  997. begin
  998. consume(_SEMICOLON);
  999. consume_all_until(_SEMICOLON);
  1000. end;
  1001. consume(_SEMICOLON);
  1002. end;
  1003. consume_emptystats;
  1004. end;
  1005. { don't consume the finalization token, it is consumed when
  1006. reading the finalization block, but allow it only after
  1007. an initalization ! }
  1008. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  1009. consume(_END);
  1010. last:=cblocknode.create(first);
  1011. last.set_tree_filepos(filepos);
  1012. statement_block:=last;
  1013. end;
  1014. function assembler_block : tnode;
  1015. var
  1016. p : tnode;
  1017. locals : longint;
  1018. begin
  1019. { Rename the funcret so that recursive calls are possible }
  1020. if not is_void(current_procinfo.procdef.rettype.def) then
  1021. symtablestack.rename(current_procinfo.procdef.resultname,'$hiddenresult');
  1022. { delphi uses register calling for assembler methods }
  1023. if (m_delphi in aktmodeswitches) and
  1024. (po_assembler in current_procinfo.procdef.procoptions) and
  1025. not(po_hascallingconvention in current_procinfo.procdef.procoptions) then
  1026. current_procinfo.procdef.proccalloption:=pocall_register;
  1027. { force the asm statement }
  1028. if token<>_ASM then
  1029. consume(_ASM);
  1030. include(current_procinfo.flags,pi_is_assembler);
  1031. p:=_asm_statement;
  1032. {$ifndef sparc}
  1033. {$ifndef arm}
  1034. if (po_assembler in current_procinfo.procdef.procoptions) then
  1035. begin
  1036. { set the framepointer to esp for assembler functions when the
  1037. following conditions are met:
  1038. - if the are no local variables and parameters (except the allocated result)
  1039. - no reference to the result variable (refcount<=1)
  1040. - result is not stored as parameter
  1041. - target processor has optional frame pointer save
  1042. (vm, i386, vm only currently)
  1043. }
  1044. locals:=0;
  1045. current_procinfo.procdef.localst.foreach_static({$ifdef FPCPROCVAR}@{$endif}count_locals,@locals);
  1046. current_procinfo.procdef.parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}count_locals,@locals);
  1047. if (locals=0) and
  1048. (current_procinfo.procdef.owner.symtabletype<>objectsymtable) and
  1049. (not assigned(current_procinfo.procdef.funcretsym) or
  1050. (tvarsym(current_procinfo.procdef.funcretsym).refcount<=1)) and
  1051. not(paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) then
  1052. begin
  1053. { Only need to set the framepointer, the locals will
  1054. be inserted with the correct reference in tcgasmnode.pass_2 }
  1055. current_procinfo.framepointer:=NR_STACK_POINTER_REG;
  1056. end;
  1057. end;
  1058. {$endif arm}
  1059. {$endif sparc}
  1060. { Flag the result as assigned when it is returned in a
  1061. register.
  1062. }
  1063. if assigned(current_procinfo.procdef.funcretsym) and
  1064. (not paramanager.ret_in_param(current_procinfo.procdef.rettype.def,current_procinfo.procdef.proccalloption)) then
  1065. tvarsym(current_procinfo.procdef.funcretsym).varstate:=vs_assigned;
  1066. { because the END is already read we need to get the
  1067. last_endtoken_filepos here (PFV) }
  1068. last_endtoken_filepos:=akttokenpos;
  1069. assembler_block:=p;
  1070. end;
  1071. end.
  1072. {
  1073. $Log$
  1074. Revision 1.139 2004-09-21 17:25:12 peter
  1075. * paraloc branch merged
  1076. Revision 1.138 2004/09/21 16:00:50 peter
  1077. * no difference for withnode when debuginfo is generated
  1078. Revision 1.137 2004/09/13 20:28:27 peter
  1079. * for loop variable assignment is not allowed anymore
  1080. Revision 1.136.4.1 2004/09/21 16:01:54 peter
  1081. * withnode debug disabled
  1082. Revision 1.136 2004/06/20 08:55:30 florian
  1083. * logs truncated
  1084. Revision 1.135 2004/06/16 20:07:09 florian
  1085. * dwarf branch merged
  1086. Revision 1.134 2004/05/23 18:28:41 peter
  1087. * methodpointer is loaded into a temp when it was a calln
  1088. Revision 1.133 2004/05/23 11:39:38 peter
  1089. * give error when goto jumps to label outside current proc scope
  1090. Revision 1.132.2.2 2004/05/01 16:02:09 peter
  1091. * POINTER_SIZE replaced with sizeof(aint)
  1092. * aint,aword,tconst*int moved to globtype
  1093. Revision 1.132.2.1 2004/04/28 19:55:52 peter
  1094. * new warning for ordinal-pointer when size is different
  1095. * fixed some cg_e_ messages to the correct section type_e_ or parser_e_
  1096. }