pstatmnt.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  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);
  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. rg.cleartempgen;
  160. do_resulttypepass(caseexpr);
  161. casedeferror:=false;
  162. casedef:=caseexpr.resulttype.def;
  163. if (not assigned(casedef)) or
  164. not(is_ordinal(casedef)) then
  165. begin
  166. CGMessage(type_e_ordinal_expr_expected);
  167. { create a correct tree }
  168. caseexpr.free;
  169. caseexpr:=cordconstnode.create(0,u32bittype,false);
  170. { set error flag so no rangechecks are done }
  171. casedeferror:=true;
  172. end;
  173. consume(_OF);
  174. inc(statement_level);
  175. root:=nil;
  176. instruc:=nil;
  177. repeat
  178. objectlibrary.getlabel(aktcaselabel);
  179. firstlabel:=true;
  180. { maybe an instruction has more case labels }
  181. repeat
  182. p:=expr;
  183. if is_widechar(casedef) then
  184. begin
  185. if (p.nodetype=rangen) then
  186. begin
  187. trangenode(p).left:=ctypeconvnode.create(trangenode(p).left,cwidechartype);
  188. trangenode(p).right:=ctypeconvnode.create(trangenode(p).right,cwidechartype);
  189. do_resulttypepass(trangenode(p).left);
  190. do_resulttypepass(trangenode(p).right);
  191. end
  192. else
  193. begin
  194. p:=ctypeconvnode.create(p,cwidechartype);
  195. do_resulttypepass(p);
  196. end;
  197. end;
  198. hl1:=0;
  199. hl2:=0;
  200. if (p.nodetype=rangen) then
  201. begin
  202. { type checking for case statements }
  203. if is_subequal(casedef, trangenode(p).left.resulttype.def) and
  204. is_subequal(casedef, trangenode(p).right.resulttype.def) then
  205. begin
  206. hl1:=get_ordinal_value(trangenode(p).left);
  207. hl2:=get_ordinal_value(trangenode(p).right);
  208. if hl1>hl2 then
  209. CGMessage(parser_e_case_lower_less_than_upper_bound);
  210. if not casedeferror then
  211. begin
  212. testrange(casedef,hl1,false);
  213. testrange(casedef,hl2,false);
  214. end;
  215. end
  216. else
  217. CGMessage(parser_e_case_mismatch);
  218. newcaselabel(hl1,hl2,firstlabel);
  219. end
  220. else
  221. begin
  222. { type checking for case statements }
  223. if not is_subequal(casedef, p.resulttype.def) then
  224. CGMessage(parser_e_case_mismatch);
  225. hl1:=get_ordinal_value(p);
  226. if not casedeferror then
  227. testrange(casedef,hl1,false);
  228. newcaselabel(hl1,hl1,firstlabel);
  229. end;
  230. p.free;
  231. if token=_COMMA then
  232. consume(_COMMA)
  233. else
  234. break;
  235. firstlabel:=false;
  236. until false;
  237. consume(_COLON);
  238. { handles instruction block }
  239. p:=clabelnode.createcase(aktcaselabel,statement);
  240. { concats instruction }
  241. instruc:=cstatementnode.create(p,instruc);
  242. if not((token=_ELSE) or (token=_OTHERWISE) or (token=_END)) then
  243. consume(_SEMICOLON);
  244. until (token=_ELSE) or (token=_OTHERWISE) or (token=_END);
  245. if (token=_ELSE) or (token=_OTHERWISE) then
  246. begin
  247. if not try_to_consume(_ELSE) then
  248. consume(_OTHERWISE);
  249. elseblock:=statements_til_end;
  250. end
  251. else
  252. begin
  253. elseblock:=nil;
  254. consume(_END);
  255. end;
  256. dec(statement_level);
  257. code:=ccasenode.create(caseexpr,instruc,root);
  258. tcasenode(code).elseblock:=elseblock;
  259. case_statement:=code;
  260. end;
  261. function repeat_statement : tnode;
  262. var
  263. first,last,p_e : tnode;
  264. begin
  265. consume(_REPEAT);
  266. first:=nil;
  267. inc(statement_level);
  268. while token<>_UNTIL do
  269. begin
  270. if first=nil then
  271. begin
  272. last:=cstatementnode.create(statement,nil);
  273. first:=last;
  274. end
  275. else
  276. begin
  277. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  278. last:=tstatementnode(last).right;
  279. end;
  280. if not try_to_consume(_SEMICOLON) then
  281. break;
  282. consume_emptystats;
  283. end;
  284. consume(_UNTIL);
  285. dec(statement_level);
  286. first:=cblocknode.create(first);
  287. p_e:=comp_expr(true);
  288. repeat_statement:=genloopnode(whilerepeatn,p_e,first,nil,true);
  289. end;
  290. function while_statement : tnode;
  291. var
  292. p_e,p_a : tnode;
  293. begin
  294. consume(_WHILE);
  295. p_e:=comp_expr(true);
  296. consume(_DO);
  297. p_a:=statement;
  298. while_statement:=genloopnode(whilerepeatn,p_e,p_a,nil,false);
  299. end;
  300. function for_statement : tnode;
  301. var
  302. p_e,tovalue,p_a : tnode;
  303. backward : boolean;
  304. begin
  305. { parse loop header }
  306. consume(_FOR);
  307. p_e:=expr;
  308. if token=_DOWNTO then
  309. begin
  310. consume(_DOWNTO);
  311. backward:=true;
  312. end
  313. else
  314. begin
  315. consume(_TO);
  316. backward:=false;
  317. end;
  318. tovalue:=comp_expr(true);
  319. consume(_DO);
  320. { ... now the instruction }
  321. p_a:=statement;
  322. for_statement:=genloopnode(forn,p_e,tovalue,p_a,backward);
  323. end;
  324. function _with_statement : tnode;
  325. var
  326. right,p : tnode;
  327. i,levelcount : longint;
  328. withsymtable,symtab : tsymtable;
  329. obj : tobjectdef;
  330. hp : tnode;
  331. begin
  332. p:=comp_expr(true);
  333. do_resulttypepass(p);
  334. set_varstate(p,false);
  335. right:=nil;
  336. if (not codegenerror) and
  337. (p.resulttype.def.deftype in [objectdef,recorddef]) then
  338. begin
  339. case p.resulttype.def.deftype of
  340. objectdef : begin
  341. obj:=tobjectdef(p.resulttype.def);
  342. symtab:=twithsymtable.Create(obj,obj.symtable.symsearch);
  343. withsymtable:=symtab;
  344. if (p.nodetype=loadn) and
  345. (tloadnode(p).symtable=aktprocdef.localst) then
  346. twithsymtable(symtab).direct_with:=true;
  347. twithsymtable(symtab).withrefnode:=p;
  348. levelcount:=1;
  349. obj:=obj.childof;
  350. while assigned(obj) do
  351. begin
  352. symtab.next:=twithsymtable.create(obj,obj.symtable.symsearch);
  353. symtab:=symtab.next;
  354. if (p.nodetype=loadn) and
  355. (tloadnode(p).symtable=aktprocdef.localst) then
  356. twithsymtable(symtab).direct_with:=true;
  357. twithsymtable(symtab).withrefnode:=p;
  358. obj:=obj.childof;
  359. inc(levelcount);
  360. end;
  361. symtab.next:=symtablestack;
  362. symtablestack:=withsymtable;
  363. end;
  364. recorddef : begin
  365. symtab:=trecorddef(p.resulttype.def).symtable;
  366. levelcount:=1;
  367. withsymtable:=twithsymtable.create(trecorddef(p.resulttype.def),symtab.symsearch);
  368. if (p.nodetype=loadn) and
  369. (tloadnode(p).symtable=aktprocdef.localst) then
  370. twithsymtable(withsymtable).direct_with:=true;
  371. twithsymtable(withsymtable).withrefnode:=p;
  372. withsymtable.next:=symtablestack;
  373. symtablestack:=withsymtable;
  374. end;
  375. end;
  376. if token=_COMMA then
  377. begin
  378. consume(_COMMA);
  379. right:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  380. end
  381. else
  382. begin
  383. consume(_DO);
  384. if token<>_SEMICOLON then
  385. right:=statement
  386. else
  387. right:=cerrornode.create;
  388. end;
  389. for i:=1 to levelcount do
  390. symtablestack:=symtablestack.next;
  391. _with_statement:=cwithnode.create(twithsymtable(withsymtable),p,right,levelcount);
  392. end
  393. else
  394. begin
  395. Message(parser_e_false_with_expr);
  396. { try to recover from error }
  397. if token=_COMMA then
  398. begin
  399. consume(_COMMA);
  400. hp:=_with_statement{$ifdef FPCPROCVAR}(){$endif};
  401. if (hp=nil) then; { remove warning about unused }
  402. end
  403. else
  404. begin
  405. consume(_DO);
  406. { ignore all }
  407. if token<>_SEMICOLON then
  408. statement;
  409. end;
  410. _with_statement:=nil;
  411. end;
  412. end;
  413. function with_statement : tnode;
  414. begin
  415. consume(_WITH);
  416. with_statement:=_with_statement;
  417. end;
  418. function raise_statement : tnode;
  419. var
  420. p,pobj,paddr,pframe : tnode;
  421. begin
  422. pobj:=nil;
  423. paddr:=nil;
  424. pframe:=nil;
  425. consume(_RAISE);
  426. if not(token in [_SEMICOLON,_END]) then
  427. begin
  428. { object }
  429. pobj:=comp_expr(true);
  430. if try_to_consume(_AT) then
  431. begin
  432. paddr:=comp_expr(true);
  433. if try_to_consume(_COMMA) then
  434. pframe:=comp_expr(true);
  435. end;
  436. end
  437. else
  438. begin
  439. if (block_type<>bt_except) then
  440. Message(parser_e_no_reraise_possible);
  441. end;
  442. p:=craisenode.create(pobj,paddr,pframe);
  443. raise_statement:=p;
  444. end;
  445. function try_statement : tnode;
  446. var
  447. p_try_block,p_finally_block,first,last,
  448. p_default,p_specific,hp : tnode;
  449. ot : ttype;
  450. sym : tvarsym;
  451. old_block_type : tblock_type;
  452. exceptsymtable : tsymtable;
  453. objname,objrealname : stringid;
  454. srsym : tsym;
  455. srsymtable : tsymtable;
  456. oldaktexceptblock: integer;
  457. begin
  458. procinfo.flags:=procinfo.flags or pi_uses_exceptions;
  459. p_default:=nil;
  460. p_specific:=nil;
  461. { read statements to try }
  462. consume(_TRY);
  463. first:=nil;
  464. inc(exceptblockcounter);
  465. oldaktexceptblock := aktexceptblock;
  466. aktexceptblock := exceptblockcounter;
  467. inc(statement_level);
  468. while (token<>_FINALLY) and (token<>_EXCEPT) do
  469. begin
  470. if first=nil then
  471. begin
  472. last:=cstatementnode.create(statement,nil);
  473. first:=last;
  474. end
  475. else
  476. begin
  477. tstatementnode(last).right:=cstatementnode.create(statement,nil);
  478. last:=tstatementnode(last).right;
  479. end;
  480. if not try_to_consume(_SEMICOLON) then
  481. break;
  482. consume_emptystats;
  483. end;
  484. p_try_block:=cblocknode.create(first);
  485. if try_to_consume(_FINALLY) then
  486. begin
  487. inc(exceptblockcounter);
  488. aktexceptblock := exceptblockcounter;
  489. p_finally_block:=statements_til_end;
  490. try_statement:=ctryfinallynode.create(p_try_block,p_finally_block);
  491. dec(statement_level);
  492. end
  493. else
  494. begin
  495. consume(_EXCEPT);
  496. old_block_type:=block_type;
  497. block_type:=bt_except;
  498. inc(exceptblockcounter);
  499. aktexceptblock := exceptblockcounter;
  500. ot:=generrortype;
  501. p_specific:=nil;
  502. if (idtoken=_ON) then
  503. { catch specific exceptions }
  504. begin
  505. repeat
  506. consume(_ID);
  507. if token=_ID then
  508. begin
  509. objname:=pattern;
  510. objrealname:=orgpattern;
  511. { can't use consume_sym here, because we need already
  512. to check for the colon }
  513. searchsym(objname,srsym,srsymtable);
  514. consume(_ID);
  515. { is a explicit name for the exception given ? }
  516. if try_to_consume(_COLON) then
  517. begin
  518. consume_sym(srsym,srsymtable);
  519. if (srsym.typ=typesym) and
  520. is_class(ttypesym(srsym).restype.def) then
  521. begin
  522. ot:=ttypesym(srsym).restype;
  523. sym:=tvarsym.create(objrealname,ot);
  524. end
  525. else
  526. begin
  527. sym:=tvarsym.create(objrealname,generrortype);
  528. if (srsym.typ=typesym) then
  529. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  530. else
  531. Message1(type_e_class_type_expected,ot.def.typename);
  532. end;
  533. exceptsymtable:=tstt_exceptsymtable.create;
  534. exceptsymtable.insert(sym);
  535. { insert the exception symtable stack }
  536. exceptsymtable.next:=symtablestack;
  537. symtablestack:=exceptsymtable;
  538. end
  539. else
  540. begin
  541. { check if type is valid, must be done here because
  542. with "e: Exception" the e is not necessary }
  543. if srsym=nil then
  544. begin
  545. identifier_not_found(objrealname);
  546. srsym:=generrorsym;
  547. end;
  548. { support unit.identifier }
  549. if srsym.typ=unitsym then
  550. begin
  551. consume(_POINT);
  552. srsym:=searchsymonlyin(tunitsym(srsym).unitsymtable,pattern);
  553. if srsym=nil then
  554. begin
  555. identifier_not_found(orgpattern);
  556. srsym:=generrorsym;
  557. end;
  558. consume(_ID);
  559. end;
  560. { check if type is valid, must be done here because
  561. with "e: Exception" the e is not necessary }
  562. if (srsym.typ=typesym) and
  563. is_class(ttypesym(srsym).restype.def) then
  564. ot:=ttypesym(srsym).restype
  565. else
  566. begin
  567. ot:=generrortype;
  568. if (srsym.typ=typesym) then
  569. Message1(type_e_class_type_expected,ttypesym(srsym).restype.def.typename)
  570. else
  571. Message1(type_e_class_type_expected,ot.def.typename);
  572. end;
  573. exceptsymtable:=nil;
  574. end;
  575. end
  576. else
  577. consume(_ID);
  578. consume(_DO);
  579. hp:=connode.create(nil,statement);
  580. if ot.def.deftype=errordef then
  581. begin
  582. hp.free;
  583. hp:=cerrornode.create;
  584. end;
  585. if p_specific=nil then
  586. begin
  587. last:=hp;
  588. p_specific:=last;
  589. end
  590. else
  591. begin
  592. tonnode(last).left:=hp;
  593. last:=tonnode(last).left;
  594. end;
  595. { set the informations }
  596. { only if the creation of the onnode was succesful, it's possible }
  597. { that last and hp are errornodes (JM) }
  598. if last.nodetype = onn then
  599. begin
  600. tonnode(last).excepttype:=tobjectdef(ot.def);
  601. tonnode(last).exceptsymtable:=exceptsymtable;
  602. end;
  603. { remove exception symtable }
  604. if assigned(exceptsymtable) then
  605. begin
  606. dellexlevel;
  607. if last.nodetype <> onn then
  608. exceptsymtable.free;
  609. end;
  610. if not try_to_consume(_SEMICOLON) then
  611. break;
  612. consume_emptystats;
  613. until (token=_END) or (token=_ELSE);
  614. if token=_ELSE then
  615. { catch the other exceptions }
  616. begin
  617. consume(_ELSE);
  618. p_default:=statements_til_end;
  619. end
  620. else
  621. consume(_END);
  622. end
  623. else
  624. { catch all exceptions }
  625. begin
  626. p_default:=statements_til_end;
  627. end;
  628. dec(statement_level);
  629. block_type:=old_block_type;
  630. try_statement:=ctryexceptnode.create(p_try_block,p_specific,p_default);
  631. end;
  632. aktexceptblock := oldaktexceptblock;
  633. end;
  634. function _asm_statement : tnode;
  635. var
  636. asmstat : tasmnode;
  637. Marker : tai;
  638. r : tregister;
  639. found : boolean;
  640. hs : string;
  641. begin
  642. Inside_asm_statement:=true;
  643. case aktasmmode of
  644. asmmode_none : ; { just be there to allow to a compile without
  645. any assembler readers }
  646. {$ifdef i386}
  647. {$ifndef NoRA386Att}
  648. asmmode_i386_att:
  649. asmstat:=tasmnode(ra386att.assemble);
  650. {$endif NoRA386Att}
  651. {$ifndef NoRA386Int}
  652. asmmode_i386_intel:
  653. asmstat:=tasmnode(ra386int.assemble);
  654. {$endif NoRA386Int}
  655. {$else not i386}
  656. asmmode_standard:
  657. asmstat:=tasmnode(rasm.assemble);
  658. {$endif i386}
  659. asmmode_direct:
  660. begin
  661. if not target_asm.allowdirect then
  662. Message(parser_f_direct_assembler_not_allowed);
  663. if (aktprocdef.proccalloption=pocall_inline) then
  664. Begin
  665. Message1(parser_w_not_supported_for_inline,'direct asm');
  666. Message(parser_w_inlining_disabled);
  667. aktprocdef.proccalloption:=pocall_fpccall;
  668. End;
  669. asmstat:=tasmnode(radirect.assemble);
  670. end;
  671. else
  672. Message(parser_f_assembler_reader_not_supported);
  673. end;
  674. { Read first the _ASM statement }
  675. consume(_ASM);
  676. { END is read }
  677. if try_to_consume(_LECKKLAMMER) then
  678. begin
  679. if token<>_RECKKLAMMER then
  680. begin
  681. repeat
  682. { it's possible to specify the modified registers }
  683. include(asmstat.flags,nf_object_preserved);
  684. hs:=upper(pattern);
  685. found:=false;
  686. for r:=low(tregister) to high(tregister) do
  687. if hs=upper(std_reg2str[r]) then
  688. begin
  689. if r = SELF_POINTER_REG then
  690. exclude(asmstat.flags,nf_object_preserved);
  691. include(rg.usedinproc,r);
  692. include(rg.usedbyproc,r);
  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);
  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:=STACK_POINTER_REG;
  918. { set the right value for parameters }
  919. dec(aktprocdef.parast.address_fixup,pointer_size);
  920. dec(procinfo.para_offset,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:=aktprocdef.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:=STACK_POINTER_REG;
  942. end;
  943. end;
  944. end;
  945. end;
  946. end;
  947. hp:=tai(hp.next);
  948. end;
  949. end;
  950. {$ifdef CHECKFORPUSH}
  951. function UsesPush(p:tasmnode):boolean;
  952. var
  953. hp : tai;
  954. begin
  955. hp:=tai(p.p_asm.first);
  956. while assigned(hp) do
  957. begin
  958. if (hp.typ=ait_instruction) and
  959. (taicpu(hp).opcode=A_PUSH) then
  960. begin
  961. UsesPush:=true;
  962. exit;
  963. end;
  964. hp:=tai(hp.next);
  965. end;
  966. UsesPush:=false;
  967. end;
  968. {$endif CHECKFORPUSH}
  969. var
  970. p : tnode;
  971. haslocals,hasparas : boolean;
  972. begin
  973. { retrieve info about locals and paras before a result
  974. is inserted in the symtable }
  975. haslocals:=(aktprocdef.localst.datasize>0);
  976. hasparas:=(aktprocdef.parast.datasize>0);
  977. { temporary space is set, while the BEGIN of the procedure }
  978. if symtablestack.symtabletype=localsymtable then
  979. procinfo.firsttemp_offset := tg.direction*symtablestack.datasize
  980. else
  981. procinfo.firsttemp_offset := 0;
  982. { assembler code does not allocate }
  983. { space for the return value }
  984. if not is_void(aktprocdef.rettype.def) then
  985. begin
  986. aktprocdef.funcretsym:=tfuncretsym.create(aktprocsym.name,aktprocdef.rettype);
  987. { insert in local symtable }
  988. { but with another name, so that recursive calls are possible }
  989. symtablestack.insert(aktprocdef.funcretsym);
  990. symtablestack.insertvardata(aktprocdef.funcretsym);
  991. symtablestack.rename(aktprocdef.funcretsym.name,'$result');
  992. { update the symtablesize back to 0 if there were no locals }
  993. if not haslocals then
  994. symtablestack.datasize:=0;
  995. { set the used registers depending on the function result }
  996. procinfo.update_usedinproc_result;
  997. end;
  998. { force the asm statement }
  999. if token<>_ASM then
  1000. consume(_ASM);
  1001. procinfo.Flags := procinfo.Flags Or pi_is_assembler;
  1002. p:=_asm_statement;
  1003. { set the framepointer to esp for assembler functions when the
  1004. following conditions are met:
  1005. - if the are no local variables
  1006. - no reference to the result variable (refcount<=1)
  1007. - result is not stored as parameter
  1008. - target processor has optional frame pointer save
  1009. (vm, i386, vm only currently)
  1010. }
  1011. if (po_assembler in aktprocdef.procoptions) and
  1012. (not haslocals) and
  1013. (not hasparas) and
  1014. (aktprocdef.owner.symtabletype<>objectsymtable) and
  1015. (not assigned(aktprocdef.funcretsym) or
  1016. (tfuncretsym(aktprocdef.funcretsym).refcount<=1)) and
  1017. not(paramanager.ret_in_param(aktprocdef.rettype.def,aktprocdef.proccalloption)) and
  1018. (target_cpu in [cpu_i386,cpu_m68k,cpu_vm])
  1019. {$ifdef CHECKFORPUSH}
  1020. and not(UsesPush(tasmnode(p)))
  1021. {$endif CHECKFORPUSH}
  1022. then
  1023. OptimizeFramePointer(tasmnode(p));
  1024. { Flag the result as assigned when it is returned in a
  1025. register.
  1026. }
  1027. if assigned(aktprocdef.funcretsym) and
  1028. paramanager.ret_in_reg(aktprocdef.rettype.def,aktprocdef.proccalloption) then
  1029. tfuncretsym(aktprocdef.funcretsym).funcretstate:=vs_assigned;
  1030. { because the END is already read we need to get the
  1031. last_endtoken_filepos here (PFV) }
  1032. last_endtoken_filepos:=akttokenpos;
  1033. assembler_block:=p;
  1034. end;
  1035. end.
  1036. {
  1037. $Log$
  1038. Revision 1.81 2002-11-27 02:37:14 peter
  1039. * case statement inlining added
  1040. * fixed inlining of write()
  1041. * switched statementnode left and right parts so the statements are
  1042. processed in the correct order when getcopy is used. This is
  1043. required for tempnodes
  1044. Revision 1.80 2002/11/25 17:43:22 peter
  1045. * splitted defbase in defutil,symutil,defcmp
  1046. * merged isconvertable and is_equal into compare_defs(_ext)
  1047. * made operator search faster by walking the list only once
  1048. Revision 1.79 2002/11/18 17:31:58 peter
  1049. * pass proccalloption to ret_in_xxx and push_xxx functions
  1050. Revision 1.78 2002/09/07 19:34:08 florian
  1051. + tcg.direction is used now
  1052. Revision 1.77 2002/09/07 15:25:07 peter
  1053. * old logs removed and tabs fixed
  1054. Revision 1.76 2002/09/07 12:16:03 carl
  1055. * second part bug report 1996 fix, testrange in cordconstnode
  1056. only called if option is set (also make parsing a tiny faster)
  1057. Revision 1.75 2002/09/02 18:40:52 peter
  1058. * fixed parsing of register names with lowercase
  1059. Revision 1.74 2002/09/01 14:43:12 peter
  1060. * fixed direct assembler for i386
  1061. Revision 1.73 2002/08/25 19:25:20 peter
  1062. * sym.insert_in_data removed
  1063. * symtable.insertvardata/insertconstdata added
  1064. * removed insert_in_data call from symtable.insert, it needs to be
  1065. called separatly. This allows to deref the address calculation
  1066. * procedures now calculate the parast addresses after the procedure
  1067. directives are parsed. This fixes the cdecl parast problem
  1068. * push_addr_param has an extra argument that specifies if cdecl is used
  1069. or not
  1070. Revision 1.72 2002/08/17 09:23:40 florian
  1071. * first part of procinfo rewrite
  1072. Revision 1.71 2002/08/16 14:24:58 carl
  1073. * issameref() to test if two references are the same (then emit no opcodes)
  1074. + ret_in_reg to replace ret_in_acc
  1075. (fix some register allocation bugs at the same time)
  1076. + save_std_register now has an extra parameter which is the
  1077. usedinproc registers
  1078. Revision 1.70 2002/08/11 14:32:27 peter
  1079. * renamed current_library to objectlibrary
  1080. Revision 1.69 2002/08/11 13:24:12 peter
  1081. * saving of asmsymbols in ppu supported
  1082. * asmsymbollist global is removed and moved into a new class
  1083. tasmlibrarydata that will hold the info of a .a file which
  1084. corresponds with a single module. Added librarydata to tmodule
  1085. to keep the library info stored for the module. In the future the
  1086. objectfiles will also be stored to the tasmlibrarydata class
  1087. * all getlabel/newasmsymbol and friends are moved to the new class
  1088. Revision 1.68 2002/08/10 14:46:30 carl
  1089. + moved target_cpu_string to cpuinfo
  1090. * renamed asmmode enum.
  1091. * assembler reader has now less ifdef's
  1092. * move from nppcmem.pas -> ncgmem.pas vec. node.
  1093. Revision 1.67 2002/08/09 19:11:44 carl
  1094. + reading of used registers in assembler routines is now
  1095. cpu-independent
  1096. Revision 1.66 2002/08/06 20:55:22 florian
  1097. * first part of ppc calling conventions fix
  1098. Revision 1.65 2002/07/28 20:45:22 florian
  1099. + added direct assembler reader for PowerPC
  1100. Revision 1.64 2002/07/20 11:57:56 florian
  1101. * types.pas renamed to defbase.pas because D6 contains a types
  1102. unit so this would conflicts if D6 programms are compiled
  1103. + Willamette/SSE2 instructions to assembler added
  1104. Revision 1.63 2002/07/19 11:41:36 daniel
  1105. * State tracker work
  1106. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1107. allows the state tracker to change while nodes automatically into
  1108. repeat nodes.
  1109. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1110. 'not(a>b)' is optimized into 'a<=b'.
  1111. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1112. by removing the notn and later switchting the true and falselabels. The
  1113. same is done with 'repeat until not a'.
  1114. Revision 1.62 2002/07/16 15:34:20 florian
  1115. * exit is now a syssym instead of a keyword
  1116. Revision 1.61 2002/07/11 14:41:28 florian
  1117. * start of the new generic parameter handling
  1118. Revision 1.60 2002/07/04 20:43:01 florian
  1119. * first x86-64 patches
  1120. Revision 1.59 2002/07/01 18:46:25 peter
  1121. * internal linker
  1122. * reorganized aasm layer
  1123. Revision 1.58 2002/05/18 13:34:13 peter
  1124. * readded missing revisions
  1125. Revision 1.57 2002/05/16 19:46:44 carl
  1126. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1127. + try to fix temp allocation (still in ifdef)
  1128. + generic constructor calls
  1129. + start of tassembler / tmodulebase class cleanup
  1130. }