pstatmnt.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332
  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,cpuinfo,
  33. { aasm }
  34. cpubase,aasmbase,aasmtai,aasmcpu,
  35. { symtable }
  36. symconst,symbase,symtype,symdef,symsym,symtable,defbase,paramgr,
  37. { pass 1 }
  38. pass_1,htypechk,
  39. nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
  40. { parser }
  41. scanner,
  42. pbase,pexpr,
  43. { codegen }
  44. rgobj,cgbase
  45. {$ifdef i386}
  46. {$ifndef NoRa386Int}
  47. ,ra386int
  48. {$endif NoRa386Int}
  49. {$ifndef NoRa386Att}
  50. ,ra386att
  51. {$endif NoRa386Att}
  52. {$ifndef NoRa386Dir}
  53. ,ra386dir
  54. {$endif NoRa386Dir}
  55. {$endif i386}
  56. {$ifdef x86_64}
  57. {$ifndef NoRax86Dir}
  58. ,rax86dir
  59. {$endif NoRax86Dir}
  60. {$endif i386}
  61. {$ifdef m68k}
  62. {$ifndef NoRa68kMot}
  63. ,ra68kmot
  64. {$endif NoRa68kMot}
  65. {$endif m68k}
  66. { codegen }
  67. {$ifdef newcg}
  68. ,cgbase
  69. {$endif newcg}
  70. ;
  71. function statement : tnode;forward;
  72. function if_statement : tnode;
  73. var
  74. ex,if_a,else_a : tnode;
  75. begin
  76. consume(_IF);
  77. ex:=comp_expr(true);
  78. consume(_THEN);
  79. if token<>_ELSE then
  80. if_a:=statement
  81. else
  82. if_a:=nil;
  83. if try_to_consume(_ELSE) then
  84. else_a:=statement
  85. else
  86. else_a:=nil;
  87. if_statement:=genloopnode(ifn,ex,if_a,else_a,false);
  88. end;
  89. { creates a block (list) of statements, til the next END token }
  90. function statements_til_end : tnode;
  91. var
  92. first,last : tstatementnode;
  93. begin
  94. first:=nil;
  95. while token<>_END do
  96. begin
  97. if first=nil then
  98. begin
  99. last:=cstatementnode.create(nil,statement);
  100. first:=last;
  101. end
  102. else
  103. begin
  104. last.left:=cstatementnode.create(nil,statement);
  105. last:=tstatementnode(last.left);
  106. end;
  107. if not try_to_consume(_SEMICOLON) then
  108. break;
  109. consume_emptystats;
  110. end;
  111. consume(_END);
  112. statements_til_end:=cblocknode.create(first);
  113. end;
  114. function case_statement : tnode;
  115. var
  116. { contains the label number of currently parsed case block }
  117. aktcaselabel : tasmlabel;
  118. firstlabel : boolean;
  119. root : pcaserecord;
  120. { the typ of the case expression }
  121. casedef : tdef;
  122. procedure newcaselabel(l,h : TConstExprInt;first:boolean);
  123. var
  124. hcaselabel : pcaserecord;
  125. procedure insertlabel(var p : pcaserecord);
  126. begin
  127. if p=nil then p:=hcaselabel
  128. else
  129. if (p^._low>hcaselabel^._low) and
  130. (p^._low>hcaselabel^._high) then
  131. if (hcaselabel^.statement = p^.statement) and
  132. (p^._low = hcaselabel^._high + 1) then
  133. begin
  134. p^._low := hcaselabel^._low;
  135. dispose(hcaselabel);
  136. end
  137. else
  138. insertlabel(p^.less)
  139. else
  140. if (p^._high<hcaselabel^._low) and
  141. (p^._high<hcaselabel^._high) then
  142. if (hcaselabel^.statement = p^.statement) and
  143. (p^._high+1 = hcaselabel^._low) then
  144. begin
  145. p^._high := hcaselabel^._high;
  146. dispose(hcaselabel);
  147. end
  148. else
  149. insertlabel(p^.greater)
  150. else Message(parser_e_double_caselabel);
  151. end;
  152. begin
  153. new(hcaselabel);
  154. hcaselabel^.less:=nil;
  155. hcaselabel^.greater:=nil;
  156. hcaselabel^.statement:=aktcaselabel;
  157. hcaselabel^.firstlabel:=first;
  158. getlabel(hcaselabel^._at);
  159. hcaselabel^._low:=l;
  160. hcaselabel^._high:=h;
  161. insertlabel(root);
  162. end;
  163. var
  164. code,caseexpr,p,instruc,elseblock : tnode;
  165. hl1,hl2 : TConstExprInt;
  166. casedeferror : boolean;
  167. begin
  168. consume(_CASE);
  169. caseexpr:=comp_expr(true);
  170. { determines result type }
  171. rg.cleartempgen;
  172. do_resulttypepass(caseexpr);
  173. casedeferror:=false;
  174. casedef:=caseexpr.resulttype.def;
  175. if (not assigned(casedef)) or
  176. not(is_ordinal(casedef)) then
  177. begin
  178. CGMessage(type_e_ordinal_expr_expected);
  179. { create a correct tree }
  180. caseexpr.free;
  181. caseexpr:=cordconstnode.create(0,u32bittype);
  182. { set error flag so no rangechecks are done }
  183. casedeferror:=true;
  184. end;
  185. consume(_OF);
  186. inc(statement_level);
  187. root:=nil;
  188. instruc:=nil;
  189. repeat
  190. getlabel(aktcaselabel);
  191. firstlabel:=true;
  192. { maybe an instruction has more case labels }
  193. repeat
  194. p:=expr;
  195. if is_widechar(casedef) then
  196. begin
  197. if (p.nodetype=rangen) then
  198. begin
  199. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  200. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  201. do_resulttypepass(trangenode(p).left);
  202. do_resulttypepass(trangenode(p).right);
  203. end
  204. else
  205. begin
  206. p:=ctypeconvnode.create(p,cwidechartype);
  207. do_resulttypepass(p);
  208. end;
  209. end;
  210. hl1:=0;
  211. hl2:=0;
  212. if (p.nodetype=rangen) then
  213. begin
  214. { type checking for case statements }
  215. if is_subequal(casedef, trangenode(p).left.resulttype.def) and
  216. is_subequal(casedef, trangenode(p).right.resulttype.def) then
  217. begin
  218. hl1:=get_ordinal_value(trangenode(p).left);
  219. hl2:=get_ordinal_value(trangenode(p).right);
  220. if hl1>hl2 then
  221. CGMessage(parser_e_case_lower_less_than_upper_bound);
  222. if not casedeferror then
  223. begin
  224. testrange(casedef,hl1,false);
  225. testrange(casedef,hl2,false);
  226. end;
  227. end
  228. else
  229. CGMessage(parser_e_case_mismatch);
  230. newcaselabel(hl1,hl2,firstlabel);
  231. end
  232. else
  233. begin
  234. { type checking for case statements }
  235. if not is_subequal(casedef, p.resulttype.def) then
  236. CGMessage(parser_e_case_mismatch);
  237. hl1:=get_ordinal_value(p);
  238. if not casedeferror then
  239. testrange(casedef,hl1,false);
  240. newcaselabel(hl1,hl1,firstlabel);
  241. end;
  242. p.free;
  243. if token=_COMMA then
  244. consume(_COMMA)
  245. else
  246. break;
  247. firstlabel:=false;
  248. until false;
  249. consume(_COLON);
  250. { handles instruction block }
  251. p:=clabelnode.createcase(aktcaselabel,statement);
  252. { concats instruction }
  253. instruc:=cstatementnode.create(instruc,p);
  254. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  255. consume(_SEMICOLON);
  256. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  257. if (token=_ELSE) or (token=_OTHERWISE) then
  258. begin
  259. if not try_to_consume(_ELSE) then
  260. consume(_OTHERWISE);
  261. elseblock:=statements_til_end;
  262. end
  263. else
  264. begin
  265. elseblock:=nil;
  266. consume(_END);
  267. end;
  268. dec(statement_level);
  269. code:=ccasenode.create(caseexpr,instruc,root);
  270. tcasenode(code).elseblock:=elseblock;
  271. case_statement:=code;
  272. end;
  273. function repeat_statement : tnode;
  274. var
  275. first,last,p_e : tnode;
  276. begin
  277. consume(_REPEAT);
  278. first:=nil;
  279. inc(statement_level);
  280. while token<>_UNTIL do
  281. begin
  282. if first=nil then
  283. begin
  284. last:=cstatementnode.create(nil,statement);
  285. first:=last;
  286. end
  287. else
  288. begin
  289. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  290. last:=tstatementnode(last).left;
  291. end;
  292. if not try_to_consume(_SEMICOLON) then
  293. break;
  294. consume_emptystats;
  295. end;
  296. consume(_UNTIL);
  297. dec(statement_level);
  298. first:=cblocknode.create(first);
  299. p_e:=comp_expr(true);
  300. repeat_statement:=genloopnode(whilerepeatn,p_e,first,nil,true);
  301. end;
  302. function while_statement : tnode;
  303. var
  304. p_e,p_a : tnode;
  305. begin
  306. consume(_WHILE);
  307. p_e:=comp_expr(true);
  308. consume(_DO);
  309. p_a:=statement;
  310. while_statement:=genloopnode(whilerepeatn,p_e,p_a,nil,false);
  311. end;
  312. function for_statement : tnode;
  313. var
  314. p_e,tovalue,p_a : tnode;
  315. backward : boolean;
  316. begin
  317. { parse loop header }
  318. consume(_FOR);
  319. p_e:=expr;
  320. if token=_DOWNTO then
  321. begin
  322. consume(_DOWNTO);
  323. backward:=true;
  324. end
  325. else
  326. begin
  327. consume(_TO);
  328. backward:=false;
  329. end;
  330. tovalue:=comp_expr(true);
  331. consume(_DO);
  332. { ... now the instruction }
  333. p_a:=statement;
  334. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  335. end;
  336. function _with_statement : tnode;
  337. var
  338. right,p : tnode;
  339. i,levelcount : longint;
  340. withsymtable,symtab : tsymtable;
  341. obj : tobjectdef;
  342. hp : tnode;
  343. begin
  344. p:=comp_expr(true);
  345. do_resulttypepass(p);
  346. set_varstate(p,false);
  347. right:=nil;
  348. if (not codegenerror) and
  349. (p.resulttype.def.deftype in [objectdef,recorddef]) then
  350. begin
  351. case p.resulttype.def.deftype of
  352. objectdef : begin
  353. obj:=tobjectdef(p.resulttype.def);
  354. symtab:=twithsymtable.Create(obj,obj.symtable.symsearch);
  355. withsymtable:=symtab;
  356. if (p.nodetype=loadn) and
  357. (tloadnode(p).symtable=aktprocdef.localst) then
  358. twithsymtable(symtab).direct_with:=true;
  359. twithsymtable(symtab).withrefnode:=p;
  360. levelcount:=1;
  361. obj:=obj.childof;
  362. while assigned(obj) do
  363. begin
  364. symtab.next:=twithsymtable.create(obj,obj.symtable.symsearch);
  365. symtab:=symtab.next;
  366. if (p.nodetype=loadn) and
  367. (tloadnode(p).symtable=aktprocdef.localst) then
  368. twithsymtable(symtab).direct_with:=true;
  369. twithsymtable(symtab).withrefnode:=p;
  370. obj:=obj.childof;
  371. inc(levelcount);
  372. end;
  373. symtab.next:=symtablestack;
  374. symtablestack:=withsymtable;
  375. end;
  376. recorddef : begin
  377. symtab:=trecorddef(p.resulttype.def).symtable;
  378. levelcount:=1;
  379. withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch);
  380. if (p.nodetype=loadn) and
  381. (tloadnode(p).symtable=aktprocdef.localst) then
  382. twithsymtable(withsymtable).direct_with:=true;
  383. twithsymtable(withsymtable).withrefnode:=p;
  384. withsymtable.next:=symtablestack;
  385. symtablestack:=withsymtable;
  386. end;
  387. end;
  388. if token=_COMMA then
  389. begin
  390. consume(_COMMA);
  391. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  392. end
  393. else
  394. begin
  395. consume(_DO);
  396. if token<>_SEMICOLON then
  397. right:=statement
  398. else
  399. right:=cerrornode.create;
  400. end;
  401. for i:=1 to levelcount do
  402. symtablestack:=symtablestack.next;
  403. _with_statement:=cwithnode.create(twithsymtable(withsymtable),p,right,levelcount);
  404. end
  405. else
  406. begin
  407. Message(parser_e_false_with_expr);
  408. { try to recover from error }
  409. if token=_COMMA then
  410. begin
  411. consume(_COMMA);
  412. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  413. if (hp=nil) then; { remove warning about unused }
  414. end
  415. else
  416. begin
  417. consume(_DO);
  418. { ignore all }
  419. if token<>_SEMICOLON then
  420. statement;
  421. end;
  422. _with_statement:=nil;
  423. end;
  424. end;
  425. function with_statement : tnode;
  426. begin
  427. consume(_WITH);
  428. with_statement:=_with_statement;
  429. end;
  430. function raise_statement : tnode;
  431. var
  432. p,pobj,paddr,pframe : tnode;
  433. begin
  434. pobj:=nil;
  435. paddr:=nil;
  436. pframe:=nil;
  437. consume(_RAISE);
  438. if not(token in [_SEMICOLON,_END]) then
  439. begin
  440. { object }
  441. pobj:=comp_expr(true);
  442. if try_to_consume(_AT) then
  443. begin
  444. paddr:=comp_expr(true);
  445. if try_to_consume(_COMMA) then
  446. pframe:=comp_expr(true);
  447. end;
  448. end
  449. else
  450. begin
  451. if (block_type<>bt_except) then
  452. Message(parser_e_no_reraise_possible);
  453. end;
  454. p:=craisenode.create(pobj,paddr,pframe);
  455. raise_statement:=p;
  456. end;
  457. function try_statement : tnode;
  458. var
  459. p_try_block,p_finally_block,first,last,
  460. p_default,p_specific,hp : tnode;
  461. ot : ttype;
  462. sym : tvarsym;
  463. old_block_type : tblock_type;
  464. exceptsymtable : tsymtable;
  465. objname,objrealname : stringid;
  466. srsym : tsym;
  467. srsymtable : tsymtable;
  468. oldaktexceptblock: integer;
  469. begin
  470. procinfo^.flags:=procinfo^.flags or pi_uses_exceptions;
  471. p_default:=nil;
  472. p_specific:=nil;
  473. { read statements to try }
  474. consume(_TRY);
  475. first:=nil;
  476. inc(exceptblockcounter);
  477. oldaktexceptblock := aktexceptblock;
  478. aktexceptblock := exceptblockcounter;
  479. inc(statement_level);
  480. while (token<>_FINALLY) and (token<>_EXCEPT) do
  481. begin
  482. if first=nil then
  483. begin
  484. last:=cstatementnode.create(nil,statement);
  485. first:=last;
  486. end
  487. else
  488. begin
  489. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  490. last:=tstatementnode(last).left;
  491. end;
  492. if not try_to_consume(_SEMICOLON) then
  493. break;
  494. consume_emptystats;
  495. end;
  496. p_try_block:=cblocknode.create(first);
  497. if try_to_consume(_FINALLY) then
  498. begin
  499. inc(exceptblockcounter);
  500. aktexceptblock := exceptblockcounter;
  501. p_finally_block:=statements_til_end;
  502. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  503. dec(statement_level);
  504. end
  505. else
  506. begin
  507. consume(_EXCEPT);
  508. old_block_type:=block_type;
  509. block_type:=bt_except;
  510. inc(exceptblockcounter);
  511. aktexceptblock := exceptblockcounter;
  512. ot:=generrortype;
  513. p_specific:=nil;
  514. if (idtoken=_ON) then
  515. { catch specific exceptions }
  516. begin
  517. repeat
  518. consume(_ID);
  519. if token=_ID then
  520. begin
  521. objname:=pattern;
  522. objrealname:=orgpattern;
  523. { can't use consume_sym here, because we need already
  524. to check for the colon }
  525. searchsym(objname,srsym,srsymtable);
  526. consume(_ID);
  527. { is a explicit name for the exception given ? }
  528. if try_to_consume(_COLON) then
  529. begin
  530. consume_sym(srsym,srsymtable);
  531. if (srsym.typ=typesym) and
  532. is_class(ttypesym(srsym).restype.def) then
  533. begin
  534. ot:=ttypesym(srsym).restype;
  535. sym:=tvarsym.create(objrealname,ot);
  536. end
  537. else
  538. begin
  539. sym:=tvarsym.create(objrealname,generrortype);
  540. if (srsym.typ=typesym) then
  541. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  542. else
  543. Message1(type_e_class_type_expected,ot.def.typename);
  544. end;
  545. exceptsymtable:=tstt_exceptsymtable.create;
  546. exceptsymtable.insert(sym);
  547. { insert the exception symtable stack }
  548. exceptsymtable.next:=symtablestack;
  549. symtablestack:=exceptsymtable;
  550. end
  551. else
  552. begin
  553. { check if type is valid, must be done here because
  554. with "e: Exception" the e is not necessary }
  555. if srsym=nil then
  556. begin
  557. identifier_not_found(objrealname);
  558. srsym:=generrorsym;
  559. end;
  560. { support unit.identifier }
  561. if srsym.typ=unitsym then
  562. begin
  563. consume(_POINT);
  564. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  565. if srsym=nil then
  566. begin
  567. identifier_not_found(orgpattern);
  568. srsym:=generrorsym;
  569. end;
  570. consume(_ID);
  571. end;
  572. { check if type is valid, must be done here because
  573. with "e: Exception" the e is not necessary }
  574. if (srsym.typ=typesym) and
  575. is_class(ttypesym(srsym).restype.def) then
  576. ot:=ttypesym(srsym).restype
  577. else
  578. begin
  579. ot:=generrortype;
  580. if (srsym.typ=typesym) then
  581. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  582. else
  583. Message1(type_e_class_type_expected,ot.def.typename);
  584. end;
  585. exceptsymtable:=nil;
  586. end;
  587. end
  588. else
  589. consume(_ID);
  590. consume(_DO);
  591. hp:=connode.create(nil,statement);
  592. if ot.def.deftype=errordef then
  593. begin
  594. hp.free;
  595. hp:=cerrornode.create;
  596. end;
  597. if p_specific=nil then
  598. begin
  599. last:=hp;
  600. p_specific:=last;
  601. end
  602. else
  603. begin
  604. tonnode(last).left:=hp;
  605. last:=tonnode(last).left;
  606. end;
  607. { set the informations }
  608. { only if the creation of the onnode was succesful, it's possible }
  609. { that last and hp are errornodes (JM) }
  610. if last.nodetype = onn then
  611. begin
  612. tonnode(last).excepttype:=tobjectdef(ot.def);
  613. tonnode(last).exceptsymtable:=exceptsymtable;
  614. end;
  615. { remove exception symtable }
  616. if assigned(exceptsymtable) then
  617. begin
  618. dellexlevel;
  619. if last.nodetype <> onn then
  620. exceptsymtable.free;
  621. end;
  622. if not try_to_consume(_SEMICOLON) then
  623. break;
  624. consume_emptystats;
  625. until (token=_END) or (token=_ELSE);
  626. if token=_ELSE then
  627. { catch the other exceptions }
  628. begin
  629. consume(_ELSE);
  630. p_default:=statements_til_end;
  631. end
  632. else
  633. consume(_END);
  634. end
  635. else
  636. { catch all exceptions }
  637. begin
  638. p_default:=statements_til_end;
  639. end;
  640. dec(statement_level);
  641. block_type:=old_block_type;
  642. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  643. end;
  644. aktexceptblock := oldaktexceptblock;
  645. end;
  646. function _asm_statement : tnode;
  647. var
  648. asmstat : tasmnode;
  649. Marker : tai;
  650. begin
  651. Inside_asm_statement:=true;
  652. case aktasmmode of
  653. asmmode_none : ; { just be there to allow to a compile without
  654. any assembler readers }
  655. {$ifdef i386}
  656. {$ifndef NoRA386Att}
  657. asmmode_i386_att:
  658. asmstat:=tasmnode(ra386att.assemble);
  659. {$endif NoRA386Att}
  660. {$ifndef NoRA386Int}
  661. asmmode_i386_intel:
  662. asmstat:=tasmnode(ra386int.assemble);
  663. {$endif NoRA386Int}
  664. {$ifndef NoRA386Dir}
  665. asmmode_i386_direct:
  666. begin
  667. if not target_asm.allowdirect then
  668. Message(parser_f_direct_assembler_not_allowed);
  669. if (aktprocdef.proccalloption=pocall_inline) then
  670. Begin
  671. Message1(parser_w_not_supported_for_inline,'direct asm');
  672. Message(parser_w_inlining_disabled);
  673. aktprocdef.proccalloption:=pocall_fpccall;
  674. End;
  675. asmstat:=tasmnode(ra386dir.assemble);
  676. end;
  677. {$endif NoRA386Dir}
  678. {$endif}
  679. {$ifdef x86_64}
  680. {$ifndef NoRA386Dir}
  681. asmmode_i386_direct:
  682. begin
  683. if not target_asm.allowdirect then
  684. Message(parser_f_direct_assembler_not_allowed);
  685. if (aktprocdef.proccalloption=pocall_inline) then
  686. Begin
  687. Message1(parser_w_not_supported_for_inline,'direct asm');
  688. Message(parser_w_inlining_disabled);
  689. aktprocdef.proccalloption:=pocall_fpccall;
  690. End;
  691. asmstat:=tasmnode(rax86dir.assemble);
  692. end;
  693. {$endif NoRA386Dir}
  694. {$endif x86_64}
  695. {$ifdef m68k}
  696. {$ifndef NoRA68kMot}
  697. asmmode_m68k_mot:
  698. asmstat:=tasmnode(ra68kmot.assemble);
  699. {$endif NoRA68kMot}
  700. {$endif}
  701. else
  702. Message(parser_f_assembler_reader_not_supported);
  703. end;
  704. { Read first the _ASM statement }
  705. consume(_ASM);
  706. { END is read }
  707. if try_to_consume(_LECKKLAMMER) then
  708. begin
  709. { it's possible to specify the modified registers }
  710. include(asmstat.flags,nf_object_preserved);
  711. if token<>_RECKKLAMMER then
  712. repeat
  713. { uppercase, because it's a CSTRING }
  714. uppervar(pattern);
  715. {$ifdef i386}
  716. if pattern='EAX' then
  717. include(rg.usedinproc,R_EAX)
  718. else if pattern='EBX' then
  719. include(rg.usedinproc,R_EBX)
  720. else if pattern='ECX' then
  721. include(rg.usedinproc,R_ECX)
  722. else if pattern='EDX' then
  723. include(rg.usedinproc,R_EDX)
  724. else if pattern='ESI' then
  725. begin
  726. include(rg.usedinproc,R_ESI);
  727. exclude(asmstat.flags,nf_object_preserved);
  728. end
  729. else if pattern='EDI' then
  730. include(rg.usedinproc,R_EDI)
  731. {$endif i386}
  732. {$ifdef x86_64}
  733. if pattern='RAX' then
  734. include(usedinproc,R_RAX)
  735. else if pattern='RBX' then
  736. include(usedinproc,R_RBX)
  737. else if pattern='RCX' then
  738. include(usedinproc,R_RCX)
  739. else if pattern='RDX' then
  740. include(usedinproc,R_RDX)
  741. else if pattern='RSI' then
  742. begin
  743. include(usedinproc,R_RSI);
  744. exclude(asmstat.flags,nf_object_preserved);
  745. end
  746. else if pattern='RDI' then
  747. include(usedinproc,R_RDI)
  748. {$endif x86_64}
  749. {$ifdef m68k}
  750. if pattern='D0' then
  751. include(rg.usedinproc,R_D0)
  752. else if pattern='D1' then
  753. include(rg.usedinproc,R_D1)
  754. else if pattern='D2' then
  755. include(rg.usedinproc,R_D2)
  756. else if pattern='D3' then
  757. include(rg.usedinproc,R_D3)
  758. else if pattern='D4' then
  759. include(rg.usedinproc,R_D4)
  760. else if pattern='D5' then
  761. include(rg.usedinproc,R_D5)
  762. else if pattern='D6' then
  763. include(rg.usedinproc,R_D6)
  764. else if pattern='D7' then
  765. include(rg.usedinproc,R_D7)
  766. else if pattern='A0' then
  767. include(rg.usedinproc,R_A0)
  768. else if pattern='A1' then
  769. include(rg.usedinproc,R_A1)
  770. else if pattern='A2' then
  771. include(rg.usedinproc,R_A2)
  772. else if pattern='A3' then
  773. include(rg.usedinproc,R_A3)
  774. else if pattern='A4' then
  775. include(rg.usedinproc,R_A4)
  776. else if pattern='A5' then
  777. include(rg.usedinproc,R_A5)
  778. {$endif m68k}
  779. {$ifdef powerpc}
  780. if pattern<>'' then
  781. internalerror(200108251)
  782. {$endif powerpc}
  783. {$IFDEF SPARC}
  784. if pattern<>'' then
  785. internalerror(200108251)
  786. {$ENDIF SPARC}
  787. else consume(_RECKKLAMMER);
  788. consume(_CSTRING);
  789. if not try_to_consume(_COMMA) then
  790. break;
  791. until false;
  792. consume(_RECKKLAMMER);
  793. end
  794. else rg.usedinproc := ALL_REGISTERS;
  795. { mark the start and the end of the assembler block
  796. this is needed for the optimizer }
  797. If Assigned(AsmStat.p_asm) Then
  798. Begin
  799. Marker := Tai_Marker.Create(AsmBlockStart);
  800. AsmStat.p_asm.Insert(Marker);
  801. Marker := Tai_Marker.Create(AsmBlockEnd);
  802. AsmStat.p_asm.Concat(Marker);
  803. End;
  804. Inside_asm_statement:=false;
  805. _asm_statement:=asmstat;
  806. end;
  807. function statement : tnode;
  808. var
  809. p : tnode;
  810. code : tnode;
  811. filepos : tfileposinfo;
  812. srsym : tsym;
  813. srsymtable : tsymtable;
  814. s : stringid;
  815. begin
  816. filepos:=akttokenpos;
  817. case token of
  818. _GOTO :
  819. begin
  820. if not(cs_support_goto in aktmoduleswitches)then
  821. Message(sym_e_goto_and_label_not_supported);
  822. consume(_GOTO);
  823. if (token<>_INTCONST) and (token<>_ID) then
  824. begin
  825. Message(sym_e_label_not_found);
  826. code:=cerrornode.create;
  827. end
  828. else
  829. begin
  830. if token=_ID then
  831. consume_sym(srsym,srsymtable)
  832. else
  833. begin
  834. searchsym(pattern,srsym,srsymtable);
  835. if srsym=nil then
  836. begin
  837. identifier_not_found(pattern);
  838. srsym:=generrorsym;
  839. srsymtable:=nil;
  840. end;
  841. consume(token);
  842. end;
  843. if srsym.typ<>labelsym then
  844. begin
  845. Message(sym_e_id_is_no_label_id);
  846. code:=cerrornode.create;
  847. end
  848. else
  849. begin
  850. code:=cgotonode.create(tlabelsym(srsym));
  851. tgotonode(code).labsym:=tlabelsym(srsym);
  852. { set flag that this label is used }
  853. tlabelsym(srsym).used:=true;
  854. end;
  855. end;
  856. end;
  857. _BEGIN :
  858. code:=statement_block(_BEGIN);
  859. _IF :
  860. code:=if_statement;
  861. _CASE :
  862. code:=case_statement;
  863. _REPEAT :
  864. code:=repeat_statement;
  865. _WHILE :
  866. code:=while_statement;
  867. _FOR :
  868. code:=for_statement;
  869. _WITH :
  870. code:=with_statement;
  871. _TRY :
  872. code:=try_statement;
  873. _RAISE :
  874. code:=raise_statement;
  875. { semicolons,else until and end are ignored }
  876. _SEMICOLON,
  877. _ELSE,
  878. _UNTIL,
  879. _END:
  880. code:=cnothingnode.create;
  881. _FAIL :
  882. begin
  883. if (aktprocdef.proctypeoption<>potype_constructor) then
  884. Message(parser_e_fail_only_in_constructor);
  885. consume(_FAIL);
  886. code:=cfailnode.create;
  887. end;
  888. _ASM :
  889. code:=_asm_statement;
  890. _EOF :
  891. Message(scan_f_end_of_file);
  892. else
  893. begin
  894. p:=expr;
  895. { When a colon follows a intconst then transform it into a label }
  896. if try_to_consume(_COLON) then
  897. begin
  898. s:=tostr(tordconstnode(p).value);
  899. p.free;
  900. searchsym(s,srsym,srsymtable);
  901. if assigned(srsym) then
  902. begin
  903. if tlabelsym(srsym).defined then
  904. Message(sym_e_label_already_defined);
  905. tlabelsym(srsym).defined:=true;
  906. p:=clabelnode.create(tlabelsym(srsym),nil);
  907. end
  908. else
  909. begin
  910. identifier_not_found(s);
  911. p:=cnothingnode.create;
  912. end;
  913. end;
  914. if p.nodetype=labeln then
  915. begin
  916. { the pointer to the following instruction }
  917. { isn't a very clean way }
  918. tlabelnode(p).left:=statement{$ifdef FPCPROCVAR}(){$endif};
  919. { be sure to have left also resulttypepass }
  920. resulttypepass(tlabelnode(p).left);
  921. end;
  922. { blockn support because a read/write is changed into a blocknode }
  923. { with a separate statement for each read/write operation (JM) }
  924. { the same is true for val() if the third parameter is not 32 bit }
  925. if not(p.nodetype in [nothingn,calln,assignn,breakn,inlinen,
  926. continuen,labeln,blockn,exitn]) then
  927. Message(cg_e_illegal_expression);
  928. { specify that we don't use the value returned by the call }
  929. { Question : can this be also improtant
  930. for inlinen ??
  931. it is used for :
  932. - dispose of temp stack space
  933. - dispose on FPU stack }
  934. if p.nodetype=calln then
  935. exclude(p.flags,nf_return_value_used);
  936. code:=p;
  937. end;
  938. end;
  939. if assigned(code) then
  940. code.set_tree_filepos(filepos);
  941. statement:=code;
  942. end;
  943. function statement_block(starttoken : ttoken) : tnode;
  944. var
  945. first,last : tnode;
  946. filepos : tfileposinfo;
  947. begin
  948. first:=nil;
  949. filepos:=akttokenpos;
  950. consume(starttoken);
  951. inc(statement_level);
  952. while not(token in [_END,_FINALIZATION]) do
  953. begin
  954. if first=nil then
  955. begin
  956. last:=cstatementnode.create(nil,statement);
  957. first:=last;
  958. end
  959. else
  960. begin
  961. tstatementnode(last).left:=cstatementnode.create(nil,statement);
  962. last:=tstatementnode(last).left;
  963. end;
  964. if (token in [_END,_FINALIZATION]) then
  965. break
  966. else
  967. begin
  968. { if no semicolon, then error and go on }
  969. if token<>_SEMICOLON then
  970. begin
  971. consume(_SEMICOLON);
  972. consume_all_until(_SEMICOLON);
  973. end;
  974. consume(_SEMICOLON);
  975. end;
  976. consume_emptystats;
  977. end;
  978. { don't consume the finalization token, it is consumed when
  979. reading the finalization block, but allow it only after
  980. an initalization ! }
  981. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  982. consume(_END);
  983. dec(statement_level);
  984. last:=cblocknode.create(first);
  985. last.set_tree_filepos(filepos);
  986. statement_block:=last;
  987. end;
  988. function assembler_block : tnode;
  989. {# Optimize the assembler block by removing all references
  990. which are via the frame pointer by replacing them with
  991. references via the stack pointer.
  992. This is only available to certain cpu targets where
  993. the frame pointer saving must be done explicitly.
  994. }
  995. procedure OptimizeFramePointer(p:tasmnode);
  996. var
  997. hp : tai;
  998. parafixup,
  999. i : longint;
  1000. begin
  1001. { replace framepointer with stackpointer }
  1002. procinfo^.framepointer:=STACK_POINTER_REG;
  1003. { set the right value for parameters }
  1004. dec(aktprocdef.parast.address_fixup,pointer_size);
  1005. dec(procinfo^.para_offset,pointer_size);
  1006. { replace all references to parameters in the instructions,
  1007. the parameters can be identified by the parafixup option
  1008. that is set. For normal user coded [ebp+4] this field is not
  1009. set }
  1010. parafixup:=aktprocdef.parast.address_fixup;
  1011. hp:=tai(p.p_asm.first);
  1012. while assigned(hp) do
  1013. begin
  1014. if hp.typ=ait_instruction then
  1015. begin
  1016. { fixup the references }
  1017. for i:=1 to taicpu(hp).ops do
  1018. begin
  1019. with taicpu(hp).oper[i-1] do
  1020. if typ=top_ref then
  1021. begin
  1022. case ref^.options of
  1023. ref_parafixup :
  1024. begin
  1025. ref^.offsetfixup:=parafixup;
  1026. ref^.base:=STACK_POINTER_REG;
  1027. end;
  1028. end;
  1029. end;
  1030. end;
  1031. end;
  1032. hp:=tai(hp.next);
  1033. end;
  1034. end;
  1035. {$ifdef CHECKFORPUSH}
  1036. function UsesPush(p:tasmnode):boolean;
  1037. var
  1038. hp : tai;
  1039. begin
  1040. hp:=tai(p.p_asm.first);
  1041. while assigned(hp) do
  1042. begin
  1043. if (hp.typ=ait_instruction) and
  1044. (taicpu(hp).opcode=A_PUSH) then
  1045. begin
  1046. UsesPush:=true;
  1047. exit;
  1048. end;
  1049. hp:=tai(hp.next);
  1050. end;
  1051. UsesPush:=false;
  1052. end;
  1053. {$endif CHECKFORPUSH}
  1054. var
  1055. p : tnode;
  1056. haslocals,hasparas : boolean;
  1057. begin
  1058. { retrieve info about locals and paras before a result
  1059. is inserted in the symtable }
  1060. haslocals:=(aktprocdef.localst.datasize>0);
  1061. hasparas:=(aktprocdef.parast.datasize>0);
  1062. { temporary space is set, while the BEGIN of the procedure }
  1063. if symtablestack.symtabletype=localsymtable then
  1064. procinfo^.firsttemp_offset := -symtablestack.datasize
  1065. else
  1066. procinfo^.firsttemp_offset := 0;
  1067. { assembler code does not allocate }
  1068. { space for the return value }
  1069. if not is_void(aktprocdef.rettype.def) then
  1070. begin
  1071. aktprocdef.funcretsym:=tfuncretsym.create(aktprocsym.name,aktprocdef.rettype);
  1072. { insert in local symtable }
  1073. { but with another name, so that recursive calls are possible }
  1074. symtablestack.insert(aktprocdef.funcretsym);
  1075. symtablestack.rename(aktprocdef.funcretsym.name,'$result');
  1076. { update the symtablesize back to 0 if there were no locals }
  1077. if not haslocals then
  1078. symtablestack.datasize:=0;
  1079. { set the used flag for the return }
  1080. if paramanager.ret_in_acc(aktprocdef.rettype.def) then
  1081. include(rg.usedinproc,accumulator);
  1082. end;
  1083. { force the asm statement }
  1084. if token<>_ASM then
  1085. consume(_ASM);
  1086. procinfo^.Flags := procinfo^.Flags Or pi_is_assembler;
  1087. p:=_asm_statement;
  1088. { set the framepointer to esp for assembler functions when the
  1089. following conditions are met:
  1090. - if the are no local variables
  1091. - no reference to the result variable (refcount<=1)
  1092. - result is not stored as parameter
  1093. - target processor has optional frame pointer save
  1094. (vm, i386, vm only currently)
  1095. }
  1096. if (po_assembler in aktprocdef.procoptions) and
  1097. (not haslocals) and
  1098. (not hasparas) and
  1099. (aktprocdef.owner.symtabletype<>objectsymtable) and
  1100. (not assigned(aktprocdef.funcretsym) or
  1101. (tfuncretsym(aktprocdef.funcretsym).refcount<=1)) and
  1102. not(paramanager.ret_in_param(aktprocdef.rettype.def)) and
  1103. (target_cpu in [cpu_i386,cpu_m68k,cpu_vm])
  1104. {$ifdef CHECKFORPUSH}
  1105. and not(UsesPush(tasmnode(p)))
  1106. {$endif CHECKFORPUSH}
  1107. then
  1108. OptimizeFramePointer(tasmnode(p));
  1109. { Flag the result as assigned when it is returned in the
  1110. accumulator or on the fpu stack }
  1111. if assigned(aktprocdef.funcretsym) and
  1112. (is_fpu(aktprocdef.rettype.def) or
  1113. paramanager.ret_in_acc(aktprocdef.rettype.def)) then
  1114. tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
  1115. { because the END is already read we need to get the
  1116. last_endtoken_filepos here (PFV) }
  1117. last_endtoken_filepos:=akttokenpos;
  1118. assembler_block:=p;
  1119. end;
  1120. end.
  1121. {
  1122. $Log$
  1123. Revision 1.64 2002-07-20 11:57:56 florian
  1124. * types.pas renamed to defbase.pas because D6 contains a types
  1125. unit so this would conflicts if D6 programms are compiled
  1126. + Willamette/SSE2 instructions to assembler added
  1127. Revision 1.63 2002/07/19 11:41:36 daniel
  1128. * State tracker work
  1129. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1130. allows the state tracker to change while nodes automatically into
  1131. repeat nodes.
  1132. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1133. 'not(a>b)' is optimized into 'a<=b'.
  1134. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1135. by removing the notn and later switchting the true and falselabels. The
  1136. same is done with 'repeat until not a'.
  1137. Revision 1.62 2002/07/16 15:34:20 florian
  1138. * exit is now a syssym instead of a keyword
  1139. Revision 1.61 2002/07/11 14:41:28 florian
  1140. * start of the new generic parameter handling
  1141. Revision 1.60 2002/07/04 20:43:01 florian
  1142. * first x86-64 patches
  1143. Revision 1.59 2002/07/01 18:46:25 peter
  1144. * internal linker
  1145. * reorganized aasm layer
  1146. Revision 1.58 2002/05/18 13:34:13 peter
  1147. * readded missing revisions
  1148. Revision 1.57 2002/05/16 19:46:44 carl
  1149. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1150. + try to fix temp allocation (still in ifdef)
  1151. + generic constructor calls
  1152. + start of tassembler / tmodulebase class cleanup
  1153. Revision 1.55 2002/05/06 19:56:42 carl
  1154. + added more patches from Mazen for SPARC port
  1155. Revision 1.54 2002/04/21 19:02:05 peter
  1156. * removed newn and disposen nodes, the code is now directly
  1157. inlined from pexpr
  1158. * -an option that will write the secondpass nodes to the .s file, this
  1159. requires EXTDEBUG define to actually write the info
  1160. * fixed various internal errors and crashes due recent code changes
  1161. Revision 1.53 2002/04/20 21:32:24 carl
  1162. + generic FPC_CHECKPOINTER
  1163. + first parameter offset in stack now portable
  1164. * rename some constants
  1165. + move some cpu stuff to other units
  1166. - remove unused constents
  1167. * fix stacksize for some targets
  1168. * fix generic size problems which depend now on EXTEND_SIZE constant
  1169. Revision 1.52 2002/04/16 16:11:17 peter
  1170. * using inherited; without a parent having the same function
  1171. will do nothing like delphi
  1172. Revision 1.51 2002/04/15 19:01:28 carl
  1173. + target_info.size_of_pointer -> pointer_Size
  1174. Revision 1.50 2002/04/14 16:53:54 carl
  1175. + asm statement uses ALL_REGISTERS
  1176. Revision 1.49 2002/03/31 20:26:36 jonas
  1177. + a_loadfpu_* and a_loadmm_* methods in tcg
  1178. * register allocation is now handled by a class and is mostly processor
  1179. independent (+rgobj.pas and i386/rgcpu.pas)
  1180. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  1181. * some small improvements and fixes to the optimizer
  1182. * some register allocation fixes
  1183. * some fpuvaroffset fixes in the unary minus node
  1184. * push/popusedregisters is now called rg.save/restoreusedregisters and
  1185. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  1186. also better optimizable)
  1187. * fixed and optimized register saving/restoring for new/dispose nodes
  1188. * LOC_FPU locations now also require their "register" field to be set to
  1189. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  1190. - list field removed of the tnode class because it's not used currently
  1191. and can cause hard-to-find bugs
  1192. Revision 1.48 2002/03/11 19:10:28 peter
  1193. * Regenerated with updated fpcmake
  1194. Revision 1.47 2002/03/04 17:54:59 peter
  1195. * allow oridinal labels again
  1196. Revision 1.46 2002/01/29 21:32:03 peter
  1197. * allow accessing locals in other lexlevel when the current assembler
  1198. routine doesn't have locals.
  1199. Revision 1.45 2002/01/24 18:25:49 peter
  1200. * implicit result variable generation for assembler routines
  1201. * removed m_tp modeswitch, use m_tp7 or not(m_fpc) instead
  1202. }