pstatmnt.pas 44 KB

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