pstatmnt.pas 42 KB

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