pstatmnt.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  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 : begin
  343. obj:=tobjectdef(p.resulttype.def);
  344. symtab:=twithsymtable.Create(obj,obj.symtable.symsearch);
  345. withsymtable:=symtab;
  346. if (p.nodetype=loadn) and
  347. (tloadnode(p).symtable=aktprocdef.localst) then
  348. twithsymtable(symtab).direct_with:=true;
  349. twithsymtable(symtab).withrefnode:=p;
  350. levelcount:=1;
  351. obj:=obj.childof;
  352. while assigned(obj) do
  353. begin
  354. symtab.next:=twithsymtable.create(obj,obj.symtable.symsearch);
  355. symtab:=symtab.next;
  356. if (p.nodetype=loadn) and
  357. (tloadnode(p).symtable=aktprocdef.localst) then
  358. twithsymtable(symtab).direct_with:=true;
  359. twithsymtable(symtab).withrefnode:=p;
  360. obj:=obj.childof;
  361. inc(levelcount);
  362. end;
  363. symtab.next:=symtablestack;
  364. symtablestack:=withsymtable;
  365. end;
  366. recorddef : begin
  367. symtab:=trecorddef(p.resulttype.def).symtable;
  368. levelcount:=1;
  369. withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch);
  370. if (p.nodetype=loadn) and
  371. (tloadnode(p).symtable=aktprocdef.localst) then
  372. twithsymtable(withsymtable).direct_with:=true;
  373. twithsymtable(withsymtable).withrefnode:=p;
  374. withsymtable.next:=symtablestack;
  375. symtablestack:=withsymtable;
  376. end;
  377. end;
  378. if token=_COMMA then
  379. begin
  380. consume(_COMMA);
  381. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  382. end
  383. else
  384. begin
  385. consume(_DO);
  386. if token<>_SEMICOLON then
  387. right:=statement
  388. else
  389. right:=cerrornode.create;
  390. end;
  391. for i:=1 to levelcount do
  392. symtablestack:=symtablestack.next;
  393. _with_statement:=cwithnode.create(twithsymtable(withsymtable),p,right,levelcount);
  394. end
  395. else
  396. begin
  397. Message(parser_e_false_with_expr);
  398. { try to recover from error }
  399. if token=_COMMA then
  400. begin
  401. consume(_COMMA);
  402. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  403. if (hp=nil) then; { remove warning about unused }
  404. end
  405. else
  406. begin
  407. consume(_DO);
  408. { ignore all }
  409. if token<>_SEMICOLON then
  410. statement;
  411. end;
  412. _with_statement:=nil;
  413. end;
  414. end;
  415. function with_statement : tnode;
  416. begin
  417. consume(_WITH);
  418. with_statement:=_with_statement;
  419. end;
  420. function raise_statement : tnode;
  421. var
  422. p,pobj,paddr,pframe : tnode;
  423. begin
  424. pobj:=nil;
  425. paddr:=nil;
  426. pframe:=nil;
  427. consume(_RAISE);
  428. if not(token in endtokens) then
  429. begin
  430. { object }
  431. pobj:=comp_expr(true);
  432. if try_to_consume(_AT) then
  433. begin
  434. paddr:=comp_expr(true);
  435. if try_to_consume(_COMMA) then
  436. pframe:=comp_expr(true);
  437. end;
  438. end
  439. else
  440. begin
  441. if (block_type<>bt_except) then
  442. Message(parser_e_no_reraise_possible);
  443. end;
  444. p:=craisenode.create(pobj,paddr,pframe);
  445. raise_statement:=p;
  446. end;
  447. function try_statement : tnode;
  448. var
  449. p_try_block,p_finally_block,first,last,
  450. p_default,p_specific,hp : tnode;
  451. ot : ttype;
  452. sym : tvarsym;
  453. old_block_type : tblock_type;
  454. exceptsymtable : tsymtable;
  455. objname,objrealname : stringid;
  456. srsym : tsym;
  457. srsymtable : tsymtable;
  458. oldaktexceptblock: integer;
  459. begin
  460. procinfo.flags:=procinfo.flags or pi_uses_exceptions;
  461. p_default:=nil;
  462. p_specific:=nil;
  463. { read statements to try }
  464. consume(_TRY);
  465. first:=nil;
  466. inc(exceptblockcounter);
  467. oldaktexceptblock := aktexceptblock;
  468. aktexceptblock := exceptblockcounter;
  469. inc(statement_level);
  470. while (token<>_FINALLY) and (token<>_EXCEPT) do
  471. begin
  472. if first=nil then
  473. begin
  474. last:=cstatementnode.create(statement,nil);
  475. first:=last;
  476. end
  477. else
  478. begin
  479. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  480. last:=tstatementnode(last).right;
  481. end;
  482. if not try_to_consume(_SEMICOLON) then
  483. break;
  484. consume_emptystats;
  485. end;
  486. p_try_block:=cblocknode.create(first,true);
  487. if try_to_consume(_FINALLY) then
  488. begin
  489. inc(exceptblockcounter);
  490. aktexceptblock := exceptblockcounter;
  491. p_finally_block:=statements_til_end;
  492. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  493. dec(statement_level);
  494. end
  495. else
  496. begin
  497. consume(_EXCEPT);
  498. old_block_type:=block_type;
  499. block_type:=bt_except;
  500. inc(exceptblockcounter);
  501. aktexceptblock := exceptblockcounter;
  502. ot:=generrortype;
  503. p_specific:=nil;
  504. if (idtoken=_ON) then
  505. { catch specific exceptions }
  506. begin
  507. repeat
  508. consume(_ID);
  509. if token=_ID then
  510. begin
  511. objname:=pattern;
  512. objrealname:=orgpattern;
  513. { can't use consume_sym here, because we need already
  514. to check for the colon }
  515. searchsym(objname,srsym,srsymtable);
  516. consume(_ID);
  517. { is a explicit name for the exception given ? }
  518. if try_to_consume(_COLON) then
  519. begin
  520. consume_sym(srsym,srsymtable);
  521. if (srsym.typ=typesym) and
  522. is_class(ttypesym(srsym).restype.def) then
  523. begin
  524. ot:=ttypesym(srsym).restype;
  525. sym:=tvarsym.create(objrealname,ot);
  526. end
  527. else
  528. begin
  529. sym:=tvarsym.create(objrealname,generrortype);
  530. if (srsym.typ=typesym) then
  531. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  532. else
  533. Message1(type_e_class_type_expected,ot.def.typename);
  534. end;
  535. exceptsymtable:=tstt_exceptsymtable.create;
  536. exceptsymtable.insert(sym);
  537. { insert the exception symtable stack }
  538. exceptsymtable.next:=symtablestack;
  539. symtablestack:=exceptsymtable;
  540. end
  541. else
  542. begin
  543. { check if type is valid, must be done here because
  544. with "e: Exception" the e is not necessary }
  545. if srsym=nil then
  546. begin
  547. identifier_not_found(objrealname);
  548. srsym:=generrorsym;
  549. end;
  550. { support unit.identifier }
  551. if srsym.typ=unitsym then
  552. begin
  553. consume(_POINT);
  554. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  555. if srsym=nil then
  556. begin
  557. identifier_not_found(orgpattern);
  558. srsym:=generrorsym;
  559. end;
  560. consume(_ID);
  561. end;
  562. { check if type is valid, must be done here because
  563. with "e: Exception" the e is not necessary }
  564. if (srsym.typ=typesym) and
  565. is_class(ttypesym(srsym).restype.def) then
  566. ot:=ttypesym(srsym).restype
  567. else
  568. begin
  569. ot:=generrortype;
  570. if (srsym.typ=typesym) then
  571. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  572. else
  573. Message1(type_e_class_type_expected,ot.def.typename);
  574. end;
  575. exceptsymtable:=nil;
  576. end;
  577. end
  578. else
  579. consume(_ID);
  580. consume(_DO);
  581. hp:=connode.create(nil,statement);
  582. if ot.def.deftype=errordef then
  583. begin
  584. hp.free;
  585. hp:=cerrornode.create;
  586. end;
  587. if p_specific=nil then
  588. begin
  589. last:=hp;
  590. p_specific:=last;
  591. end
  592. else
  593. begin
  594. tonnode(last).left:=hp;
  595. last:=tonnode(last).left;
  596. end;
  597. { set the informations }
  598. { only if the creation of the onnode was succesful, it's possible }
  599. { that last and hp are errornodes (JM) }
  600. if last.nodetype = onn then
  601. begin
  602. tonnode(last).excepttype:=tobjectdef(ot.def);
  603. tonnode(last).exceptsymtable:=exceptsymtable;
  604. end;
  605. { remove exception symtable }
  606. if assigned(exceptsymtable) then
  607. begin
  608. dellexlevel;
  609. if last.nodetype <> onn then
  610. exceptsymtable.free;
  611. end;
  612. if not try_to_consume(_SEMICOLON) then
  613. break;
  614. consume_emptystats;
  615. until (token in [_END,_ELSE]);
  616. if try_to_consume(_ELSE) then
  617. begin
  618. { catch the other exceptions }
  619. p_default:=statements_til_end;
  620. end
  621. else
  622. consume(_END);
  623. end
  624. else
  625. begin
  626. { catch all exceptions }
  627. p_default:=statements_til_end;
  628. end;
  629. dec(statement_level);
  630. block_type:=old_block_type;
  631. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  632. end;
  633. aktexceptblock := oldaktexceptblock;
  634. end;
  635. function _asm_statement : tnode;
  636. var
  637. asmstat : tasmnode;
  638. Marker : tai;
  639. r : tregister;
  640. found : boolean;
  641. hs : string;
  642. begin
  643. Inside_asm_statement:=true;
  644. case aktasmmode of
  645. asmmode_none : ; { just be there to allow to a compile without
  646. any assembler readers }
  647. {$ifdef i386}
  648. {$ifndef NoRA386Att}
  649. asmmode_i386_att:
  650. asmstat:=tasmnode(ra386att.assemble);
  651. {$endif NoRA386Att}
  652. {$ifndef NoRA386Int}
  653. asmmode_i386_intel:
  654. asmstat:=tasmnode(ra386int.assemble);
  655. {$endif NoRA386Int}
  656. {$else not i386}
  657. asmmode_standard:
  658. asmstat:=tasmnode(rasm.assemble);
  659. {$endif i386}
  660. asmmode_direct:
  661. begin
  662. if not target_asm.allowdirect then
  663. Message(parser_f_direct_assembler_not_allowed);
  664. if (aktprocdef.proccalloption=pocall_inline) then
  665. Begin
  666. Message1(parser_w_not_supported_for_inline,'direct asm');
  667. Message(parser_w_inlining_disabled);
  668. aktprocdef.proccalloption:=pocall_fpccall;
  669. End;
  670. asmstat:=tasmnode(radirect.assemble);
  671. end;
  672. else
  673. Message(parser_f_assembler_reader_not_supported);
  674. end;
  675. { Read first the _ASM statement }
  676. consume(_ASM);
  677. { END is read }
  678. if try_to_consume(_LECKKLAMMER) then
  679. begin
  680. if token<>_RECKKLAMMER then
  681. begin
  682. repeat
  683. { it's possible to specify the modified registers }
  684. hs:=upper(pattern);
  685. found:=false;
  686. for r.enum:=firstreg to lastreg do
  687. if hs=upper(std_reg2str[r.enum]) then
  688. begin
  689. include(rg.usedinproc,r.enum);
  690. include(rg.usedbyproc,r.enum);
  691. found:=true;
  692. break;
  693. end;
  694. if not(found) then
  695. Message(asmr_e_invalid_register);
  696. consume(_CSTRING);
  697. if not try_to_consume(_COMMA) then
  698. break;
  699. until false;
  700. end;
  701. consume(_RECKKLAMMER);
  702. end
  703. else
  704. begin
  705. rg.usedbyproc := ALL_REGISTERS;
  706. rg.usedinproc := ALL_REGISTERS;
  707. end;
  708. { mark the start and the end of the assembler block
  709. this is needed for the optimizer }
  710. If Assigned(AsmStat.p_asm) Then
  711. Begin
  712. Marker := Tai_Marker.Create(AsmBlockStart);
  713. AsmStat.p_asm.Insert(Marker);
  714. Marker := Tai_Marker.Create(AsmBlockEnd);
  715. AsmStat.p_asm.Concat(Marker);
  716. End;
  717. Inside_asm_statement:=false;
  718. _asm_statement:=asmstat;
  719. end;
  720. function statement : tnode;
  721. var
  722. p : tnode;
  723. code : tnode;
  724. filepos : tfileposinfo;
  725. srsym : tsym;
  726. srsymtable : tsymtable;
  727. s : stringid;
  728. begin
  729. filepos:=akttokenpos;
  730. case token of
  731. _GOTO :
  732. begin
  733. if not(cs_support_goto in aktmoduleswitches)then
  734. Message(sym_e_goto_and_label_not_supported);
  735. consume(_GOTO);
  736. if (token<>_INTCONST) and (token<>_ID) then
  737. begin
  738. Message(sym_e_label_not_found);
  739. code:=cerrornode.create;
  740. end
  741. else
  742. begin
  743. if token=_ID then
  744. consume_sym(srsym,srsymtable)
  745. else
  746. begin
  747. searchsym(pattern,srsym,srsymtable);
  748. if srsym=nil then
  749. begin
  750. identifier_not_found(pattern);
  751. srsym:=generrorsym;
  752. srsymtable:=nil;
  753. end;
  754. consume(token);
  755. end;
  756. if srsym.typ<>labelsym then
  757. begin
  758. Message(sym_e_id_is_no_label_id);
  759. code:=cerrornode.create;
  760. end
  761. else
  762. begin
  763. code:=cgotonode.create(tlabelsym(srsym));
  764. tgotonode(code).labsym:=tlabelsym(srsym);
  765. { set flag that this label is used }
  766. tlabelsym(srsym).used:=true;
  767. end;
  768. end;
  769. end;
  770. _BEGIN :
  771. code:=statement_block(_BEGIN);
  772. _IF :
  773. code:=if_statement;
  774. _CASE :
  775. code:=case_statement;
  776. _REPEAT :
  777. code:=repeat_statement;
  778. _WHILE :
  779. code:=while_statement;
  780. _FOR :
  781. code:=for_statement;
  782. _WITH :
  783. code:=with_statement;
  784. _TRY :
  785. code:=try_statement;
  786. _RAISE :
  787. code:=raise_statement;
  788. { semicolons,else until and end are ignored }
  789. _SEMICOLON,
  790. _ELSE,
  791. _UNTIL,
  792. _END:
  793. code:=cnothingnode.create;
  794. _FAIL :
  795. begin
  796. if (aktprocdef.proctypeoption<>potype_constructor) then
  797. Message(parser_e_fail_only_in_constructor);
  798. consume(_FAIL);
  799. code:=cfailnode.create;
  800. end;
  801. _ASM :
  802. code:=_asm_statement;
  803. _EOF :
  804. Message(scan_f_end_of_file);
  805. else
  806. begin
  807. p:=expr;
  808. { When a colon follows a intconst then transform it into a label }
  809. if try_to_consume(_COLON) then
  810. begin
  811. s:=tostr(tordconstnode(p).value);
  812. p.free;
  813. searchsym(s,srsym,srsymtable);
  814. if assigned(srsym) then
  815. begin
  816. if tlabelsym(srsym).defined then
  817. Message(sym_e_label_already_defined);
  818. tlabelsym(srsym).defined:=true;
  819. p:=clabelnode.create(tlabelsym(srsym),nil);
  820. end
  821. else
  822. begin
  823. identifier_not_found(s);
  824. p:=cnothingnode.create;
  825. end;
  826. end;
  827. if p.nodetype=labeln then
  828. begin
  829. { the pointer to the following instruction }
  830. { isn't a very clean way }
  831. tlabelnode(p).left:=statement{$ifdef FPCPROCVAR}(){$endif};
  832. { be sure to have left also resulttypepass }
  833. resulttypepass(tlabelnode(p).left);
  834. end;
  835. { blockn support because a read/write is changed into a blocknode }
  836. { with a separate statement for each read/write operation (JM) }
  837. { the same is true for val() if the third parameter is not 32 bit }
  838. if not(p.nodetype in [nothingn,calln,assignn,breakn,inlinen,
  839. continuen,labeln,blockn,exitn]) then
  840. Message(cg_e_illegal_expression);
  841. { specify that we don't use the value returned by the call }
  842. { Question : can this be also improtant
  843. for inlinen ??
  844. it is used for :
  845. - dispose of temp stack space
  846. - dispose on FPU stack }
  847. if p.nodetype=calln then
  848. exclude(p.flags,nf_return_value_used);
  849. code:=p;
  850. end;
  851. end;
  852. if assigned(code) then
  853. code.set_tree_filepos(filepos);
  854. statement:=code;
  855. end;
  856. function statement_block(starttoken : ttoken) : tnode;
  857. var
  858. first,last : tnode;
  859. filepos : tfileposinfo;
  860. begin
  861. first:=nil;
  862. filepos:=akttokenpos;
  863. consume(starttoken);
  864. inc(statement_level);
  865. while not(token in [_END,_FINALIZATION]) do
  866. begin
  867. if first=nil then
  868. begin
  869. last:=cstatementnode.create(statement,nil);
  870. first:=last;
  871. end
  872. else
  873. begin
  874. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  875. last:=tstatementnode(last).right;
  876. end;
  877. if (token in [_END,_FINALIZATION]) then
  878. break
  879. else
  880. begin
  881. { if no semicolon, then error and go on }
  882. if token<>_SEMICOLON then
  883. begin
  884. consume(_SEMICOLON);
  885. consume_all_until(_SEMICOLON);
  886. end;
  887. consume(_SEMICOLON);
  888. end;
  889. consume_emptystats;
  890. end;
  891. { don't consume the finalization token, it is consumed when
  892. reading the finalization block, but allow it only after
  893. an initalization ! }
  894. if (starttoken<>_INITIALIZATION) or (token<>_FINALIZATION) then
  895. consume(_END);
  896. dec(statement_level);
  897. last:=cblocknode.create(first,true);
  898. last.set_tree_filepos(filepos);
  899. statement_block:=last;
  900. end;
  901. function assembler_block : tnode;
  902. {# Optimize the assembler block by removing all references
  903. which are via the frame pointer by replacing them with
  904. references via the stack pointer.
  905. This is only available to certain cpu targets where
  906. the frame pointer saving must be done explicitly.
  907. }
  908. procedure OptimizeFramePointer(p:tasmnode);
  909. var
  910. hp : tai;
  911. parafixup,
  912. i : longint;
  913. begin
  914. { we don't need to allocate space for the locals }
  915. aktprocdef.localst.datasize:=0;
  916. procinfo.firsttemp_offset:=0;
  917. { replace framepointer with stackpointer }
  918. procinfo.framepointer.enum:=R_INTREGISTER;
  919. procinfo.framepointer.number:=NR_STACK_POINTER_REG;
  920. { set the right value for parameters }
  921. dec(aktprocdef.parast.address_fixup,pointer_size);
  922. dec(procinfo.para_offset,pointer_size);
  923. { replace all references to parameters in the instructions,
  924. the parameters can be identified by the parafixup option
  925. that is set. For normal user coded [ebp+4] this field is not
  926. set }
  927. parafixup:=aktprocdef.parast.address_fixup;
  928. hp:=tai(p.p_asm.first);
  929. while assigned(hp) do
  930. begin
  931. if hp.typ=ait_instruction then
  932. begin
  933. { fixup the references }
  934. for i:=1 to taicpu(hp).ops do
  935. begin
  936. with taicpu(hp).oper[i-1] do
  937. if typ=top_ref then
  938. begin
  939. case ref^.options of
  940. ref_parafixup :
  941. begin
  942. ref^.offsetfixup:=parafixup;
  943. ref^.base.enum:=R_INTREGISTER;
  944. ref^.base.number:=NR_STACK_POINTER_REG;
  945. end;
  946. end;
  947. end;
  948. end;
  949. end;
  950. hp:=tai(hp.next);
  951. end;
  952. end;
  953. {$ifdef CHECKFORPUSH}
  954. function UsesPush(p:tasmnode):boolean;
  955. var
  956. hp : tai;
  957. begin
  958. hp:=tai(p.p_asm.first);
  959. while assigned(hp) do
  960. begin
  961. if (hp.typ=ait_instruction) and
  962. (taicpu(hp).opcode=A_PUSH) then
  963. begin
  964. UsesPush:=true;
  965. exit;
  966. end;
  967. hp:=tai(hp.next);
  968. end;
  969. UsesPush:=false;
  970. end;
  971. {$endif CHECKFORPUSH}
  972. var
  973. p : tnode;
  974. begin
  975. { Rename the funcret so that recursive calls are possible }
  976. if not is_void(aktprocdef.rettype.def) then
  977. symtablestack.rename(aktprocdef.funcretsym.name,'$result');
  978. { force the asm statement }
  979. if token<>_ASM then
  980. consume(_ASM);
  981. procinfo.Flags := procinfo.Flags Or pi_is_assembler;
  982. p:=_asm_statement;
  983. { set the framepointer to esp for assembler functions when the
  984. following conditions are met:
  985. - if the are no local variables (except the allocated result)
  986. - if the are no parameters
  987. - no reference to the result variable (refcount<=1)
  988. - result is not stored as parameter
  989. - target processor has optional frame pointer save
  990. (vm, i386, vm only currently)
  991. }
  992. if (po_assembler in aktprocdef.procoptions) and
  993. (aktprocdef.parast.datasize=0) and
  994. (aktprocdef.localst.datasize=aktprocdef.rettype.def.size) and
  995. (aktprocdef.owner.symtabletype<>objectsymtable) and
  996. (not assigned(aktprocdef.funcretsym) or
  997. (tfuncretsym(aktprocdef.funcretsym).refcount<=1)) and
  998. not(paramanager.ret_in_param(aktprocdef.rettype.def,aktprocdef.proccalloption)) and
  999. (target_cpu in [cpu_i386,cpu_m68k,cpu_vm])
  1000. {$ifdef CHECKFORPUSH}
  1001. and not(UsesPush(tasmnode(p)))
  1002. {$endif CHECKFORPUSH}
  1003. then
  1004. OptimizeFramePointer(tasmnode(p));
  1005. { Flag the result as assigned when it is returned in a
  1006. register.
  1007. }
  1008. if assigned(aktprocdef.funcretsym) and
  1009. paramanager.ret_in_reg(aktprocdef.rettype.def,aktprocdef.proccalloption) then
  1010. tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
  1011. { because the END is already read we need to get the
  1012. last_endtoken_filepos here (PFV) }
  1013. last_endtoken_filepos:=akttokenpos;
  1014. assembler_block:=p;
  1015. end;
  1016. end.
  1017. {
  1018. $Log$
  1019. Revision 1.90 2002-04-25 20:15:40 florian
  1020. * block nodes within expressions shouldn't release the used registers,
  1021. fixed using a flag till the new rg is ready
  1022. Revision 1.89 2003/04/25 08:25:26 daniel
  1023. * Ifdefs around a lot of calls to cleartempgen
  1024. * Fixed registers that are allocated but not freed in several nodes
  1025. * Tweak to register allocator to cause less spills
  1026. * 8-bit registers now interfere with esi,edi and ebp
  1027. Compiler can now compile rtl successfully when using new register
  1028. allocator
  1029. Revision 1.88 2003/03/28 19:16:57 peter
  1030. * generic constructor working for i386
  1031. * remove fixed self register
  1032. * esi added as address register for i386
  1033. Revision 1.87 2003/03/17 18:55:30 peter
  1034. * allow more tokens instead of only semicolon after inherited
  1035. Revision 1.86 2003/02/19 22:00:14 daniel
  1036. * Code generator converted to new register notation
  1037. - Horribily outdated todo.txt removed
  1038. Revision 1.85 2003/01/08 18:43:56 daniel
  1039. * Tregister changed into a record
  1040. Revision 1.84 2003/01/01 21:05:24 peter
  1041. * fixed assembler methods stackpointer optimization that was
  1042. broken after the previous change
  1043. Revision 1.83 2002/12/29 18:59:34 peter
  1044. * fixed parsing of declarations before asm statement
  1045. Revision 1.82 2002/12/27 18:18:56 peter
  1046. * check for else after empty raise statement
  1047. Revision 1.81 2002/11/27 02:37:14 peter
  1048. * case statement inlining added
  1049. * fixed inlining of write()
  1050. * switched statementnode left and right parts so the statements are
  1051. processed in the correct order when getcopy is used. This is
  1052. required for tempnodes
  1053. Revision 1.80 2002/11/25 17:43:22 peter
  1054. * splitted defbase in defutil,symutil,defcmp
  1055. * merged isconvertable and is_equal into compare_defs(_ext)
  1056. * made operator search faster by walking the list only once
  1057. Revision 1.79 2002/11/18 17:31:58 peter
  1058. * pass proccalloption to ret_in_xxx and push_xxx functions
  1059. Revision 1.78 2002/09/07 19:34:08 florian
  1060. + tcg.direction is used now
  1061. Revision 1.77 2002/09/07 15:25:07 peter
  1062. * old logs removed and tabs fixed
  1063. Revision 1.76 2002/09/07 12:16:03 carl
  1064. * second part bug report 1996 fix, testrange in cordconstnode
  1065. only called if option is set (also make parsing a tiny faster)
  1066. Revision 1.75 2002/09/02 18:40:52 peter
  1067. * fixed parsing of register names with lowercase
  1068. Revision 1.74 2002/09/01 14:43:12 peter
  1069. * fixed direct assembler for i386
  1070. Revision 1.73 2002/08/25 19:25:20 peter
  1071. * sym.insert_in_data removed
  1072. * symtable.insertvardata/insertconstdata added
  1073. * removed insert_in_data call from symtable.insert, it needs to be
  1074. called separatly. This allows to deref the address calculation
  1075. * procedures now calculate the parast addresses after the procedure
  1076. directives are parsed. This fixes the cdecl parast problem
  1077. * push_addr_param has an extra argument that specifies if cdecl is used
  1078. or not
  1079. Revision 1.72 2002/08/17 09:23:40 florian
  1080. * first part of procinfo rewrite
  1081. Revision 1.71 2002/08/16 14:24:58 carl
  1082. * issameref() to test if two references are the same (then emit no opcodes)
  1083. + ret_in_reg to replace ret_in_acc
  1084. (fix some register allocation bugs at the same time)
  1085. + save_std_register now has an extra parameter which is the
  1086. usedinproc registers
  1087. Revision 1.70 2002/08/11 14:32:27 peter
  1088. * renamed current_library to objectlibrary
  1089. Revision 1.69 2002/08/11 13:24:12 peter
  1090. * saving of asmsymbols in ppu supported
  1091. * asmsymbollist global is removed and moved into a new class
  1092. tasmlibrarydata that will hold the info of a .a file which
  1093. corresponds with a single module. Added librarydata to tmodule
  1094. to keep the library info stored for the module. In the future the
  1095. objectfiles will also be stored to the tasmlibrarydata class
  1096. * all getlabel/newasmsymbol and friends are moved to the new class
  1097. Revision 1.68 2002/08/10 14:46:30 carl
  1098. + moved target_cpu_string to cpuinfo
  1099. * renamed asmmode enum.
  1100. * assembler reader has now less ifdef's
  1101. * move from nppcmem.pas -> ncgmem.pas vec. node.
  1102. Revision 1.67 2002/08/09 19:11:44 carl
  1103. + reading of used registers in assembler routines is now
  1104. cpu-independent
  1105. Revision 1.66 2002/08/06 20:55:22 florian
  1106. * first part of ppc calling conventions fix
  1107. Revision 1.65 2002/07/28 20:45:22 florian
  1108. + added direct assembler reader for PowerPC
  1109. Revision 1.64 2002/07/20 11:57:56 florian
  1110. * types.pas renamed to defbase.pas because D6 contains a types
  1111. unit so this would conflicts if D6 programms are compiled
  1112. + Willamette/SSE2 instructions to assembler added
  1113. Revision 1.63 2002/07/19 11:41:36 daniel
  1114. * State tracker work
  1115. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1116. allows the state tracker to change while nodes automatically into
  1117. repeat nodes.
  1118. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1119. 'not(a>b)' is optimized into 'a<=b'.
  1120. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1121. by removing the notn and later switchting the true and falselabels. The
  1122. same is done with 'repeat until not a'.
  1123. Revision 1.62 2002/07/16 15:34:20 florian
  1124. * exit is now a syssym instead of a keyword
  1125. Revision 1.61 2002/07/11 14:41:28 florian
  1126. * start of the new generic parameter handling
  1127. Revision 1.60 2002/07/04 20:43:01 florian
  1128. * first x86-64 patches
  1129. Revision 1.59 2002/07/01 18:46:25 peter
  1130. * internal linker
  1131. * reorganized aasm layer
  1132. Revision 1.58 2002/05/18 13:34:13 peter
  1133. * readded missing revisions
  1134. Revision 1.57 2002/05/16 19:46:44 carl
  1135. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1136. + try to fix temp allocation (still in ifdef)
  1137. + generic constructor calls
  1138. + start of tassembler / tmodulebase class cleanup
  1139. }