pstatmnt.pas 44 KB

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