pstatmnt.pas 44 KB

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