pstatmnt.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317
  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=current_procdef.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=current_procdef.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=current_procdef.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. include(current_procinfo.flags,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. symtablestack:=symtablestack.next;
  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 (current_procdef.proccalloption=pocall_inline) then
  667. Begin
  668. Message1(parser_w_not_supported_for_inline,'direct asm');
  669. Message(parser_w_inlining_disabled);
  670. current_procdef.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 (current_procdef.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. current_procinfo.framepointer.enum:=R_INTREGISTER;
  918. current_procinfo.framepointer.number:=NR_STACK_POINTER_REG;
  919. { set the right value for parameters }
  920. dec(current_procdef.parast.address_fixup,pointer_size);
  921. { replace all references to parameters in the instructions,
  922. the parameters can be identified by the parafixup option
  923. that is set. For normal user coded [ebp+4] this field is not
  924. set }
  925. parafixup:=current_procdef.parast.address_fixup;
  926. hp:=tai(p.p_asm.first);
  927. while assigned(hp) do
  928. begin
  929. if hp.typ=ait_instruction then
  930. begin
  931. { fixup the references }
  932. for i:=1 to taicpu(hp).ops do
  933. begin
  934. with taicpu(hp).oper[i-1] do
  935. if typ=top_ref then
  936. begin
  937. case ref^.options of
  938. ref_parafixup :
  939. begin
  940. ref^.offsetfixup:=parafixup;
  941. ref^.base.enum:=R_INTREGISTER;
  942. ref^.base.number:=NR_STACK_POINTER_REG;
  943. end;
  944. end;
  945. end;
  946. end;
  947. end;
  948. hp:=tai(hp.next);
  949. end;
  950. end;
  951. {$ifdef CHECKFORPUSH}
  952. function UsesPush(p:tasmnode):boolean;
  953. var
  954. hp : tai;
  955. begin
  956. hp:=tai(p.p_asm.first);
  957. while assigned(hp) do
  958. begin
  959. if (hp.typ=ait_instruction) and
  960. (taicpu(hp).opcode=A_PUSH) then
  961. begin
  962. UsesPush:=true;
  963. exit;
  964. end;
  965. hp:=tai(hp.next);
  966. end;
  967. UsesPush:=false;
  968. end;
  969. {$endif CHECKFORPUSH}
  970. var
  971. p : tnode;
  972. begin
  973. { Rename the funcret so that recursive calls are possible }
  974. if not is_void(current_procdef.rettype.def) then
  975. symtablestack.rename(current_procdef.resultname,'$hiddenresult');
  976. { force the asm statement }
  977. if token<>_ASM then
  978. consume(_ASM);
  979. include(current_procinfo.flags,pi_is_assembler);
  980. p:=_asm_statement;
  981. { set the framepointer to esp for assembler functions when the
  982. following conditions are met:
  983. - if the are no local variables (except the allocated result)
  984. - if the are no parameters
  985. - no reference to the result variable (refcount<=1)
  986. - result is not stored as parameter
  987. - target processor has optional frame pointer save
  988. (vm, i386, vm only currently)
  989. }
  990. if (po_assembler in current_procdef.procoptions) and
  991. {$ifndef powerpc}
  992. { is this really necessary??? }
  993. (current_procdef.parast.datasize=0) and
  994. {$endif powerpc}
  995. (current_procdef.localst.datasize=current_procdef.rettype.def.size) and
  996. (current_procdef.owner.symtabletype<>objectsymtable) and
  997. (not assigned(current_procdef.funcretsym) or
  998. (tvarsym(current_procdef.funcretsym).refcount<=1)) and
  999. not(paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption)) then
  1000. begin
  1001. { we don't need to allocate space for the locals }
  1002. current_procdef.localst.datasize:=0;
  1003. current_procinfo.firsttemp_offset:=0;
  1004. { only for cpus with different frame- and stack pointer the code must be changed }
  1005. if (NR_STACK_POINTER_REG<>NR_FRAME_POINTER_REG)
  1006. {$ifdef CHECKFORPUSH}
  1007. and not(UsesPush(tasmnode(p)))
  1008. {$endif CHECKFORPUSH}
  1009. then
  1010. OptimizeFramePointer(tasmnode(p));
  1011. end;
  1012. { Flag the result as assigned when it is returned in a
  1013. register.
  1014. }
  1015. if assigned(current_procdef.funcretsym) and
  1016. (not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption)) then
  1017. tvarsym(current_procdef.funcretsym).varstate:=vs_assigned;
  1018. { because the END is already read we need to get the
  1019. last_endtoken_filepos here (PFV) }
  1020. last_endtoken_filepos:=akttokenpos;
  1021. assembler_block:=p;
  1022. end;
  1023. end.
  1024. {
  1025. $Log$
  1026. Revision 1.94 2003-04-27 11:21:34 peter
  1027. * aktprocdef renamed to current_procdef
  1028. * procinfo renamed to current_procinfo
  1029. * procinfo will now be stored in current_module so it can be
  1030. cleaned up properly
  1031. * gen_main_procsym changed to create_main_proc and release_main_proc
  1032. to also generate a tprocinfo structure
  1033. * fixed unit implicit initfinal
  1034. Revision 1.93 2003/04/27 07:29:50 peter
  1035. * current_procdef cleanup, current_procdef is now always nil when parsing
  1036. a new procdef declaration
  1037. * aktprocsym removed
  1038. * lexlevel removed, use symtable.symtablelevel instead
  1039. * implicit init/final code uses the normal genentry/genexit
  1040. * funcret state checking updated for new funcret handling
  1041. Revision 1.92 2003/04/26 11:30:59 florian
  1042. * fixed the powerpc to work with the new function result handling
  1043. Revision 1.91 2003/04/25 20:59:34 peter
  1044. * removed funcretn,funcretsym, function result is now in varsym
  1045. and aliases for result and function name are added using absolutesym
  1046. * vs_hidden parameter for funcret passed in parameter
  1047. * vs_hidden fixes
  1048. * writenode changed to printnode and released from extdebug
  1049. * -vp option added to generate a tree.log with the nodetree
  1050. * nicer printnode for statements, callnode
  1051. Revision 1.90 2002/04/25 20:15:40 florian
  1052. * block nodes within expressions shouldn't release the used registers,
  1053. fixed using a flag till the new rg is ready
  1054. Revision 1.89 2003/04/25 08:25:26 daniel
  1055. * Ifdefs around a lot of calls to cleartempgen
  1056. * Fixed registers that are allocated but not freed in several nodes
  1057. * Tweak to register allocator to cause less spills
  1058. * 8-bit registers now interfere with esi,edi and ebp
  1059. Compiler can now compile rtl successfully when using new register
  1060. allocator
  1061. Revision 1.88 2003/03/28 19:16:57 peter
  1062. * generic constructor working for i386
  1063. * remove fixed self register
  1064. * esi added as address register for i386
  1065. Revision 1.87 2003/03/17 18:55:30 peter
  1066. * allow more tokens instead of only semicolon after inherited
  1067. Revision 1.86 2003/02/19 22:00:14 daniel
  1068. * Code generator converted to new register notation
  1069. - Horribily outdated todo.txt removed
  1070. Revision 1.85 2003/01/08 18:43:56 daniel
  1071. * Tregister changed into a record
  1072. Revision 1.84 2003/01/01 21:05:24 peter
  1073. * fixed assembler methods stackpointer optimization that was
  1074. broken after the previous change
  1075. Revision 1.83 2002/12/29 18:59:34 peter
  1076. * fixed parsing of declarations before asm statement
  1077. Revision 1.82 2002/12/27 18:18:56 peter
  1078. * check for else after empty raise statement
  1079. Revision 1.81 2002/11/27 02:37:14 peter
  1080. * case statement inlining added
  1081. * fixed inlining of write()
  1082. * switched statementnode left and right parts so the statements are
  1083. processed in the correct order when getcopy is used. This is
  1084. required for tempnodes
  1085. Revision 1.80 2002/11/25 17:43:22 peter
  1086. * splitted defbase in defutil,symutil,defcmp
  1087. * merged isconvertable and is_equal into compare_defs(_ext)
  1088. * made operator search faster by walking the list only once
  1089. Revision 1.79 2002/11/18 17:31:58 peter
  1090. * pass proccalloption to ret_in_xxx and push_xxx functions
  1091. Revision 1.78 2002/09/07 19:34:08 florian
  1092. + tcg.direction is used now
  1093. Revision 1.77 2002/09/07 15:25:07 peter
  1094. * old logs removed and tabs fixed
  1095. Revision 1.76 2002/09/07 12:16:03 carl
  1096. * second part bug report 1996 fix, testrange in cordconstnode
  1097. only called if option is set (also make parsing a tiny faster)
  1098. Revision 1.75 2002/09/02 18:40:52 peter
  1099. * fixed parsing of register names with lowercase
  1100. Revision 1.74 2002/09/01 14:43:12 peter
  1101. * fixed direct assembler for i386
  1102. Revision 1.73 2002/08/25 19:25:20 peter
  1103. * sym.insert_in_data removed
  1104. * symtable.insertvardata/insertconstdata added
  1105. * removed insert_in_data call from symtable.insert, it needs to be
  1106. called separatly. This allows to deref the address calculation
  1107. * procedures now calculate the parast addresses after the procedure
  1108. directives are parsed. This fixes the cdecl parast problem
  1109. * push_addr_param has an extra argument that specifies if cdecl is used
  1110. or not
  1111. Revision 1.72 2002/08/17 09:23:40 florian
  1112. * first part of procinfo rewrite
  1113. Revision 1.71 2002/08/16 14:24:58 carl
  1114. * issameref() to test if two references are the same (then emit no opcodes)
  1115. + ret_in_reg to replace ret_in_acc
  1116. (fix some register allocation bugs at the same time)
  1117. + save_std_register now has an extra parameter which is the
  1118. usedinproc registers
  1119. Revision 1.70 2002/08/11 14:32:27 peter
  1120. * renamed current_library to objectlibrary
  1121. Revision 1.69 2002/08/11 13:24:12 peter
  1122. * saving of asmsymbols in ppu supported
  1123. * asmsymbollist global is removed and moved into a new class
  1124. tasmlibrarydata that will hold the info of a .a file which
  1125. corresponds with a single module. Added librarydata to tmodule
  1126. to keep the library info stored for the module. In the future the
  1127. objectfiles will also be stored to the tasmlibrarydata class
  1128. * all getlabel/newasmsymbol and friends are moved to the new class
  1129. Revision 1.68 2002/08/10 14:46:30 carl
  1130. + moved target_cpu_string to cpuinfo
  1131. * renamed asmmode enum.
  1132. * assembler reader has now less ifdef's
  1133. * move from nppcmem.pas -> ncgmem.pas vec. node.
  1134. Revision 1.67 2002/08/09 19:11:44 carl
  1135. + reading of used registers in assembler routines is now
  1136. cpu-independent
  1137. Revision 1.66 2002/08/06 20:55:22 florian
  1138. * first part of ppc calling conventions fix
  1139. Revision 1.65 2002/07/28 20:45:22 florian
  1140. + added direct assembler reader for PowerPC
  1141. Revision 1.64 2002/07/20 11:57:56 florian
  1142. * types.pas renamed to defbase.pas because D6 contains a types
  1143. unit so this would conflicts if D6 programms are compiled
  1144. + Willamette/SSE2 instructions to assembler added
  1145. Revision 1.63 2002/07/19 11:41:36 daniel
  1146. * State tracker work
  1147. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1148. allows the state tracker to change while nodes automatically into
  1149. repeat nodes.
  1150. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1151. 'not(a>b)' is optimized into 'a<=b'.
  1152. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1153. by removing the notn and later switchting the true and falselabels. The
  1154. same is done with 'repeat until not a'.
  1155. Revision 1.62 2002/07/16 15:34:20 florian
  1156. * exit is now a syssym instead of a keyword
  1157. Revision 1.61 2002/07/11 14:41:28 florian
  1158. * start of the new generic parameter handling
  1159. Revision 1.60 2002/07/04 20:43:01 florian
  1160. * first x86-64 patches
  1161. Revision 1.59 2002/07/01 18:46:25 peter
  1162. * internal linker
  1163. * reorganized aasm layer
  1164. Revision 1.58 2002/05/18 13:34:13 peter
  1165. * readded missing revisions
  1166. Revision 1.57 2002/05/16 19:46:44 carl
  1167. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1168. + try to fix temp allocation (still in ifdef)
  1169. + generic constructor calls
  1170. + start of tassembler / tmodulebase class cleanup
  1171. }